通过DataBinding在UserControl中设置自定义属性

时间:2009-05-10 15:58:27

标签: wpf

假设我有一个非常简单的UserControl - 对于所有意图和目的 - 只不过是TextBox:

public partial class FooBox : UserControl
{
    public static readonly DependencyProperty FooTextProperty =
        DependencyProperty.Register("FooText", typeof(string), typeof(FooBox));

    public FooBox()
    {
        InitializeComponent();
    }

    public string FooText
    {
        get { return textBlock.Text; }
        set { textBlock.Text = value; }
    }
}

<UserControl x:Class="Namespace.FooBox"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="300" Width="300">
    <Grid>
        <TextBlock x:Name="textBlock" />
    </Grid>
</UserControl>

在表单上声明为:

<local:FooBox FooText="{Binding Name}" />

表单的DataContext设置为具有Name属性的对象。但这不适合我。我错过了什么?

2 个答案:

答案 0 :(得分:19)

DependencyProperty中属性声明的“get”和“set”部分实际上并没有被WPF的数据绑定系统调用 - 它们基本上只是为了满足编译器。

相反,请将您的属性声明更改为:

public string FooText
{
    get { return (string)GetValue(FooTextProperty); }
    set { SetValue(FooTextProperty, value); }
}

...和您的XAML:

<UserControl ...
    x:Name="me">
    <Grid>
        <TextBlock Text="{Binding FooText,ElementName=me}" />
    </Grid>
</UserControl>

现在你的TextBox.Text直接绑定到“FooText”属性,所以你可以将FooText属性绑定到“Name”,就像你现在正在做的那样。

另一种方法是将TextBlock.Text绑定到一个RelativeSource绑定,该绑定在类型为“FooBox”的第一个祖先上找到FooText属性,但我发现这比仅给控件一个内部x更复杂:名称并使用元素绑定。

答案 1 :(得分:6)

原来真正的问题是我期待WPF框架设置我的公共属性,然后我的代码将响应更改并根据新值进行渲染。不是这样。 WPF所做的是直接调用SetValue()并完全绕过公共属性。我必须做的是使用DependencyPropertyDescriptor.AddValueChanged接收属性更改通知并对其做出响应。它看起来像(在ctor里面):

var dpd = DependencyPropertyDescriptor
    .FromProperty(MyDependencyProperty, typeof(MyClass));
dpd.AddValueChanged(this, (sender, args) =>
{
    // Do my updating.
});