【问题标题】:Setting Custom Properties in UserControl via DataBinding通过 DataBinding 在 UserControl 中设置自定义属性
【发布时间】:2010-10-25 03:19:44
【问题描述】:

假设我有一个非常简单的 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 属性的对象。但这对我不起作用。我错过了什么?

【问题讨论】:

    标签: wpf


    【解决方案1】:

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

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

    【讨论】:

    • 另请注意,依赖属性的 Register 方法具有重载,可以接受在属性更改或已更改时触发的事件处理程序。那可能是一个放置逻辑的地方。
    【解决方案2】:

    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:Name 更复杂并使用元素绑定。

    【讨论】:

    • 我会投票给你,因为你帮助我接近了我所缺少的东西。但是我这里的测试用例太简单了,无法暴露真正的问题。看我的回答。
    猜你喜欢
    • 2011-02-16
    • 1970-01-01
    • 1970-01-01
    • 2014-03-21
    • 1970-01-01
    • 2014-03-31
    • 1970-01-01
    • 2017-10-05
    • 2020-06-17
    相关资源
    最近更新 更多