简体   繁体   English

WPF绑定混乱:复合DependencyObject

[英]WPF Binding Confusion: Composite DependencyObject

I have a DependencyObject class composition that looks like the following: 我有一个如下的DependencyObject类组成:

public class A : DependencyObject {
    public AB AB { get { ... } set { ... } }
    public AB AC { get { ... } set { ... } }
}

public class AB : DependencyObject {
    public string Property1 { get { ... } set { ... } }
    public string Property2 { get { ... } set { ... } }
    public string Property3 { get { ... } set { ... } }
}

public class AC : DependencyObject {
    public string Property1 { get { ... } set { ... } }
    public string Property2 { get { ... } set { ... } }
}

On A, AB and AC all properties perform the typical GetValue and SetValue operations referencing static properties per usual. 在A,AB和AC上,所有属性通常执行通常引用静态属性的典型GetValue和SetValue操作。

Now, classes A, AB and AC have corresponding UserControls AGroupBox, ABGrid, ACGrid. 现在,类A,AB和AC具有相应的UserControls AGroupBox,ABGrid,ACGrid。 AGroupBox has a root A class property, ABGrid has a root AB class property and ACGrid has a root AC class property. AGroupBox具有根A类的根属性,ABGrid具有根AB类的根属性,而ACGrid具有根AC类的根属性。

Both ABGrid and ACGrid have working bindings (eg, ABGrid Contains a TextBox control whose Text property is twoway bound to AB's Property1.) I've verified this by creating a simple Window and having ABGrid be Window's only Content child and in the code behind setting ABGrid.AB = new AB(); ABGrid和ACGrid都具有有效的绑定(例如,ABGrid包含一个TextBox控件,其Text属性双向绑定到AB的Property1。)我已经通过创建一个简单的Window并将ABGrid成为Window的唯一Content子对象以及设置背后的代码来验证了这一点。 ABGrid.AB =新的AB(); same scenario for ACGrid.AC = new AC();. ACGrid.AC = new AC();的情况相同。

The problem is when I try to do similarlly with with AGroupBox. 问题是当我尝试对AGroupBox进行类似处理时。 I try adding AGroupBox as the single child of Window's Content in XAML, and set the AGroupBox.A property to new A() {AB = new AB(), AC = new AC()}; 我尝试将AGroupBox添加为XAML中Window内容的单个子项,并将AGroupBox.A属性设置为new A(){AB = new AB(),AC = new AC()}; and the binding of the controls fails. 并且控件的绑定失败。 AB and AC have default values for their PropertyN properties. AB和AC具有其PropertyN属性的默认值。

Any insights on what I'm missing? 关于我所缺少的任何见解? Is there a different route I should be taking? 我应该走其他路线吗?

EDIT: Additional Comment- If I add a string property to A, (String1) and bind it to the Text part of the GroupBox then the binding to that property works, but not to the AC and AB property of A. 编辑:附加注释-如果我将字符串属性添加到A,(String1)并将其绑定到GroupBox的Text部分,则对该属性的绑定有效,但对A的AC和AB属性无效。

EDIT-2: Per David Hay's request (all code is in namespace wpfStackOverflow): EDIT-2:根据David Hay的请求(所有代码都在命名空间wpfStackOverflow中):

A.cs A.cs

public class A : DependencyObject {
    static public DependencyProperty BProperty { get; private set; }
    static public DependencyProperty CProperty { get; private set; }
    static public DependencyProperty PropertyProperty { get; private set; }

    static A() {
        BProperty = DependencyProperty.Register("B", typeof(B), typeof(A));
        CProperty = DependencyProperty.Register("C", typeof(C), typeof(A));
        PropertyProperty = DependencyProperty.Register("Property", typeof(string), typeof(A));
    }

    public B B {
        get { return (B)GetValue(BProperty); }
        set { SetValue(BProperty, value); }
    }

    public C C {
        get { return (C)GetValue(CProperty); }
        set { SetValue(CProperty, value); }
    }

    public string Property {
        get { return (string)GetValue(PropertyProperty); }
        set { SetValue(PropertyProperty, value); }
    }

    public A() {
        Property = "A's Default Value";
        B = new B();
        C = new C();
    }
}

B.cs B.cs

public class B : DependencyObject {
    static public DependencyProperty PropertyProperty { get; private set; }

    static B() {
        PropertyProperty = DependencyProperty.Register("Property", typeof(string), typeof(B));
    }

    public string Property {
        get { return (string)GetValue(PropertyProperty); }
        set { SetValue(PropertyProperty, value); }
    }

    public B() {
        Property = "B's Default Value";
    }
}

C.cs 抄送

public class C : DependencyObject {
    static public DependencyProperty PropertyProperty { get; private set; }

    static C() {
        PropertyProperty = DependencyProperty.Register("Property", typeof(string), typeof(C));
    }

    public string Property {
        get { return (string)GetValue(PropertyProperty); }
        set { SetValue(PropertyProperty, value); }
    }

    public C() {
        Property = "C's Default Value";
    }
}

AGroupBox.xaml AGroupBox.xaml

<UserControl 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:wpfStackOverflow"
    x:Class="wpfStackOverflow.AGroupBox"
    DataContext="{Binding RelativeSource={RelativeSource Self}, Path=A}"
    Width="300"
    Height="72"
    >
    <GroupBox Header="{Binding Property}">
        <StackPanel >
            <local:BGrid B="{Binding B}"/>
            <local:CGrid C="{Binding C}"/>
        </StackPanel>
    </GroupBox>
</UserControl>

AGroupBox.xaml.cs AGroupBox.xaml.cs

public partial class AGroupBox : UserControl {
    static public DependencyProperty AProperty { get; private set; }

    static AGroupBox() {
        AProperty = DependencyProperty.Register("A", typeof(A), typeof(AGroupBox));
    }

    public A A {
        get { return (A)GetValue(AProperty); }
        set { SetValue(AProperty, value); }
    }

    public AGroupBox() {
        InitializeComponent();
    }
}

BGrid.xaml BGrid.xaml

<UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="wpfStackOverflow.BGrid"
    DataContext="{Binding RelativeSource={RelativeSource Self}, Path=B}"
    >
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition />
        </Grid.ColumnDefinitions>

        <Label Grid.Column="0" Content="Property"/>
        <TextBox Grid.Column="1" Text="{Binding Property}"/>
    </Grid>
</UserControl>

BGrid.xaml.cs BGrid.xaml.cs

public partial class BGrid : UserControl {
    static public DependencyProperty BProperty { get; private set; }

    static BGrid() {
        BProperty = DependencyProperty.Register("B", typeof(B), typeof(BGrid));
    }

    public B B {
        get { return (B)GetValue(BProperty); }
        set { SetValue(BProperty, value); }
    }

    public BGrid() {
        InitializeComponent();
    }
}

CGrid.xaml CGrid.xaml

<UserControl 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="wpfStackOverflow.CGrid"
    DataContext="{Binding RelativeSource={RelativeSource Self}, Path=C}"
    >
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition />
        </Grid.ColumnDefinitions>

        <Label Grid.Column="0" Content="Property"/>
        <TextBox Grid.Column="1" Text="{Binding Property}"/>
    </Grid>
</UserControl>

CGrid.xaml.cs CGrid.xaml.cs

public partial class CGrid : UserControl {
    static public DependencyProperty CProperty { get; private set; }

    static CGrid() {
        CProperty = DependencyProperty.Register("C", typeof(C), typeof(CGrid));
    }

    public C C {
        get { return (C)GetValue(CProperty); }
        set { SetValue(CProperty, value); }
    }

    public CGrid() {
        InitializeComponent();
    }
}

window1.xaml window1.xaml

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:wpfStackOverflow"
    x:Class="wpfStackOverflow.Window1"
    Width="400"
    Height="200"
>
    <local:AGroupBox x:Name="aGroupBox" />
</Window>

Window1.xaml.cs Window1.xaml.cs

public partial class Window1 : Window {
    public Window1() {
        InitializeComponent();

        aGroupBox.A = new A()
        {
            Property = "A's Custom Property Value",
            B = new B()
            {
                Property = "B's Custom Property Value"
            },
            C = new C()
            {
                Property = "C's Custom Property Value"
            }
        };
    }
}

Try substituting the following into AGroupBox.xaml 尝试将以下内容替换为AGroupBox.xaml

<local:BGrid B="{Binding Path=A.B, RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type local:AGroupBox}}}"/>
<local:CGrid C="{Binding Path=A.C, RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type local:AGroupBox}}}"/>

It was not resolving the datacontext properly for those two lines, and so was not looking in the right place for B and C. 它没有为这两行正确地解析数据上下文,因此没有为B和C寻找合适的位置。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM