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

xan*_*ont 14 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>
Run Code Online (Sandbox Code Playgroud)

在表格上,它被声明为:

<local:FooBox FooText="{Binding Name}" />
Run Code Online (Sandbox Code Playgroud)

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

Mat*_*ton 20

在DependencyProperty中的属性声明的"get"和"set"部分实际上并不是由WPF的数据绑定系统调用的 - 它们基本上只是为了满足编译器.

相反,将您的属性声明更改为如下所示:

public string FooText
{
    get { return (string)GetValue(FooTextProperty); }
    set { SetValue(FooTextProperty, value); }
}
Run Code Online (Sandbox Code Playgroud)

......和你的XAML:

<UserControl ...
    x:Name="me">
    <Grid>
        <TextBlock Text="{Binding FooText,ElementName=me}" />
    </Grid>
</UserControl>
Run Code Online (Sandbox Code Playgroud)

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

另一种方法是将TextBlock.Text绑定到一个RelativeSource绑定,该绑定在类型为"FooBox"的第一个祖先上找到FooText属性,但我发现这比仅给控件一个内部x:Name和using元素更复杂捆绑.


xan*_*ont 6

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

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

  • 另请注意,依赖项属性的Register方法具有重载,可以接受在属性更改或更改时触发的事件处理程序.这可能是一个放置你的逻辑的地方. (4认同)