【问题标题】:WPF: DependencyProperty works on TextBlock but not on custom controlWPF:DependencyProperty 适用于 TextBlock 但不适用于自定义控件
【发布时间】:2017-10-02 10:54:45
【问题描述】:

编辑:可以在here找到一个示例项目。

我在主窗口中使用ListBox,稍后我将其绑定到ObservableCollection。我同时使用TextBlock 和绑定到集合的相同属性的自定义控件。我的问题是 TextBlock 得到正确更新,而自定义控件没有(它是默认构造的,但它的 Text 属性永远不会被绑定更新)。

<ListBox Name="MyCustomItemList">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <TextBlock Text="{Binding ItemText}"/>
                <local:MyCustomBlock Text="{Binding ItemText}"/>
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

我使用 Text 依赖属性将 MyCustomBlock 实现为 System.Windows.Controls.Canvas 的子级:

public class MyCustomBlock : Canvas
{
    public MyCustomBlock() => Text = "<default>";
    public MyCustomBlock(string text) => Text = text;

    private static void TextChangedCallback(DependencyObject o,
                                            DependencyPropertyChangedEventArgs e)
    {
        ...
    }

    public string Text
    {
        get => (string)GetValue(TextProperty);
        set => SetValue(TextProperty, value);
    }

    public static readonly DependencyProperty TextProperty =
        DependencyProperty.Register(
              nameof(Text), typeof(string), typeof(MyCustomBlock),
              new FrameworkPropertyMetadata("", TextChangedCallback));
}

最后,这是我在MainWindow构造函数中绑定到ListBox的数据:

public class MyCustomItem
{
    public MyCustomItem(string text) => ItemText = text;
    public string ItemText { get; set; }
}

public MainWindow()
{
    InitializeComponent();

    var list = new ObservableCollection<MyCustomItem>();
    list.Add(new MyCustomItem("Hello"));
    list.Add(new MyCustomItem("World"));
    MyCustomItemList.ItemsSource = list;
}

我是否忘记了设置中的某些内容?怎么TextBlock.Text貌似更新了,MyCustomBlock.Text却没有?

【问题讨论】:

  • 您如何验证自定义控件中的属性不会被绑定更新?
  • 所以你已经在 TextChangedCallback 中设置了一个断点并且它从未被命中?
  • 是的,我在TextChangedCallback 中添加了一个断点,并且在默认构造MyCustomBlock 时调用它(因此,Text 设置为"&lt;default&gt;")但它永远不会在之后调用那个。
  • 如果没有在构造函数中设置Text属性怎么办?无论如何,这样做似乎是多余的。您也可以使用"&lt;default&gt;" 作为属性元数据中的默认属性值。为了确定,您没有在某处显式设置控件的 DataContext?
  • 构造函数中设置的值具有“本地”precedence 并覆盖由创建控件实例的模板设置的任何内容。

标签: c# wpf xaml dependency-properties


【解决方案1】:

依赖属性可以从多个来源获取它们的值,因此 WPF 使用precedence 系统来确定应用哪个值。 “本地”值(使用 SetValueSetBinding 提供)将覆盖创建模板提供的任何内容。

在您的情况下,您在构造函数中设置了一个“本地”值(可能打算将其作为默认值)。设置默认值的更好方法是在 PropertyMetadata 中提供它。

public static readonly DependencyProperty TextProperty =
    DependencyProperty.Register(
          nameof(Text), typeof(string), typeof(MyCustomBlock),
          new FrameworkPropertyMetadata("<default>", TextChangedCallback));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-08
    • 1970-01-01
    • 2021-10-02
    • 2014-10-26
    • 2012-05-02
    • 2011-02-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多