3

3番目のUIオブジェクト(この例ではボタン)を参照できる2つのクラスがあるとします。

さらに、親クラスには子クラスの要素を含めることができます。

両方が同じコントロールにバインドされている場合、同じ方法で、子は失敗しますが、親は成功します。

これはWPFのバグですか?


親 :

class MyFrameworkElement : FrameworkElement
{
    // A depenedency property that will contain a child element sub-element
    private static readonly DependencyProperty ChildElementProperty =
                    DependencyProperty.Register("ChildElement",
                    typeof(MyChildElement),
                    typeof(MyFrameworkElement),
                    new PropertyMetadata());

    [Category("ChildProperties")]
    public MyChildElement ChildElement
    {
        set { SetValue(ChildElementProperty, value); }
        get { return (MyChildElement)GetValue(ChildElementProperty); }
    }


    // Now, a reference to some other control, in this case we will bind a button to it!
    public UIElement ButtonReferenceInParent
    {
        get { return (UIElement)GetValue(ButtonReferenceInParentProperty); }
        set { SetValue(ButtonReferenceInParentProperty, value); }
    }

    // Using a DependencyProperty as the backing store for ButtonReferenceInParent.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ButtonReferenceInParentProperty =
        DependencyProperty.Register("ButtonReferenceInParent", typeof(UIElement), typeof(MyFrameworkElement), new UIPropertyMetadata(null));

そして子供:

public class MyChildElement : FrameworkElement
{
    public UIElement ButtonReferenceInChild
    {
        get { return (UIElement)GetValue(ButtonReferenceInChildProperty); }
        set { SetValue(ButtonReferenceInChildProperty, value); }
    }

    public static readonly DependencyProperty ButtonReferenceInChildProperty =
        DependencyProperty.Register("ButtonReferenceInChild", typeof(UIElement), typeof(MyChildElement), new UIPropertyMetadata(null));
}

わかった -

次に、次のようにXAMLに追加するとします。

<Grid>
    <my:MyFrameworkElement x:Name="ParentName" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ButtonReferenceInParent="{Binding ElementName=buttonisme}">
        <my:MyFrameworkElement.ChildElement>
            <my:MyChildElement x:Name="ChildName" ButtonReferenceInChild="{Binding ElementName=buttonisme}"/>
        </my:MyFrameworkElement.ChildElement>
    </my:MyFrameworkElement>
    
    <Button x:Name="buttonisme" Click="buttonisme_Click" />
</Grid>

まったく同じ表記を使用しているのに、バインディングが親で機能するのに子で失敗するのはなぜですか?


これが私のテストコードです...

     Console.WriteLine("Parent button reference is {0}", ParentName.ButtonReferenceInParent);

        if (ChildName.ButtonReferenceInChild == null)
        {
            Console.WriteLine("Child button reference is null!");
        } 
        else
        {
            Console.WriteLine("Child button is {0}", ChildName.ButtonReferenceInChild);
        }

そして、これがテスト結果です...

親ボタンの参照はSystem.Windows.Controls.Buttonです。

子ボタンの参照はnullです!

4

2 に答える 2

6

長い質問に対する簡単な答えは、Microsoftは、少し配管を行わずにFrameworkElementから派生することを期待していないということです。

派生を行うだけで、要素名によるバインディングを行うときに使用される論理ツリーが壊れます。

また、おそらくビジュアルツリーを盛り上げ、フレームワーク要素の配置/測定部分をオーバーロードする必要があります。(例では視覚的ではないため、ここではこれを行いません。)

この特定のケースでは、オブジェクトの子を論理ツリーに追加するか、子要素をバインドする機能を解除する必要があります。

これを解決した人の良い例はここにあります

論理ツリーのオーバーライドに関する情報はここにあります

とにかく、このSIMPLEの例を修正するために必要なコードは、論理ツリーのみに依存していました(子オブジェクトは実際には視覚的ではないため)。

この関数を追加し、依存関係プロパティを変更すると、バインディングが機能します。

        private static readonly DependencyProperty ChildElementProperty =
                    DependencyProperty.Register("ChildElement",
                    typeof(MyChildElement),
                    typeof(MyFrameworkElement),
                    new PropertyMetadata(OnChildElementChanged));

    private static void OnChildElementChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        MyFrameworkElement control = d as MyFrameworkElement;

        if (e.OldValue != null)
        {
            control.RemoveLogicalChild(e.OldValue);
        }

        control.AddLogicalChild(e.NewValue);
    }
于 2012-10-10T07:42:11.190 に答える
-1

まず、次のようにxamlを設定する場合:

<my:MyFrameworkElement x:Name="ParentName" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ButtonReferenceInParent="{Binding ElementName=buttonisme}"/>
<my:MyChildElement x:Name="ChildName" ButtonReferenceInChild="{Binding ElementName=buttonisme}"/>

できます。これを行ったのは、バインディングで使用している要素名のビジュアルツリー上向きトラバーサル検索が疑われるためです。

ネストされたシナリオでバインディングを成功させる方法をまだ理解しています。しかし、多分これはあなたにいくつかのヒントを与えるかもしれません...

于 2012-10-01T10:21:52.940 に答える