WPF绑定混淆:复合DependencyObject

时间:2009-12-07 16:08:54

标签: c# user-controls binding dependencyobject

我有一个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 { ... } }
}

在A,AB和AC上,所有属性都执行典型的GetValue和SetValue操作,这些操作引用静态属性。

现在,A,AB和AC类具有相应的UserControls AGroupBox,ABGrid,ACGrid。 AGroupBox具有根A类属性,ABGrid具有根AB类属性,而ACGrid具有根AC类属性。

ABGrid和ACGrid都有工作绑定(例如,ABGrid包含一个TextBox控件,其Text属性是双向绑定到AB的Property1。)我已经通过创建一个简单的Window并让ABGrid成为Window唯一的Content子元素来验证这一点。设置背后的代码ABGrid.AB = new AB(); ACGrid.AC = new AC();的相同场景。

问题是当我尝试与AGroupBox类似时。我尝试将AGroupBox添加为XAML中Window的内容的单个子节点,并将AGroupBox.A属性设置为new A(){AB = new AB(),AC = new AC()};并且控件的绑定失败。 AB和AC的PropertyN属性具有默认值。

对我遗失的任何见解?我应该采取不同的路线吗?

编辑:附加注释 - 如果我将字符串属性添加到A,(String1)并将其绑定到GroupBox的Text部分,则绑定到该属性,但不能到A的AC和AB属性。 / p>

EDIT-2:Per David Hay的请求(所有代码都在名称空间wpfStackOverflow中):

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

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

<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

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

<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

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

<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

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

<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

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"
            }
        };
    }
}

1 个答案:

答案 0 :(得分:1)

尝试将以下内容替换为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}}}"/>

这两行没有正确解析datacontext,所以没有找到适合B和C的地方。