【问题标题】:WPF - DependencyProperty ignoring setter with side-effects on change [duplicate]WPF - DependencyProperty 忽略设置器,对更改有副作用
【发布时间】:2015-04-01 13:33:04
【问题描述】:

我有一个 WPF 用户控件,它是另外两个控件的包装器,根据情况只显示其中一个。它拥有一个ItemsSource 属性,该属性为两个底层控件设置ItemsSource。我想让这个属性可以绑定到一个 .xaml 文件。

我创建了一个DependencyProperty,并更改了我的getter 和setter 以使用它。但是,当我调试代码时,我可以看到 setter 永远不会被调用。我可以看到依赖属性正在改变它的值,但它没有设置底层控件的属性。

我怎样才能让底层控件在依赖属性更改时设置其属性?

public partial class AccountSelector : UserControl
{
    public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register(
        "ItemsSource", typeof(IEnumerable), typeof(AccountSelector));
    public IEnumerable ItemsSource
    {
        get
        {
            return (IEnumerable)GetValue(ItemsSourceProperty);
        }
        set
        {
            if (UseComboBox)
                AccCombo.ItemsSource = value;
            else
                AccComplete.ItemsSource = value;
            SetValue(ItemsSourceProperty, value);
        }
    }
}

【问题讨论】:

  • 属性的值是否已设置但可能不会被提升到 UI?此外,您将属性声明为只读,这将阻止分配给它,除非在同一类的构造函数或声明中。有关只读的更多信息,请参阅here

标签: c# wpf data-binding wpf-controls


【解决方案1】:

您必须将 propertyChangedCallback 传递给您的 UIPropertyMetadata,如下所示:

    public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register(
        "ItemsSource", typeof(IEnumerable), typeof(AccountSelector), new UIPropertyMetadata((d, e) =>
        {
            if (e.NewValue == null) return;

            var s = d as AccountSelector;
            var list = e.NewValue as IEnumerable;

            if (list == null || s == null) return;
            if (s.UseComboBox)
                s.AccCombo.ItemsSource = list;
            else
                s.AccComplete.ItemsSource = list;                
        }));
    public IEnumerable ItemsSource
    {
        get
        {
            return (IEnumerable)GetValue(ItemsSourceProperty);
        }
        set
        {
            SetValue(ItemsSourceProperty, value);
        }
    }

【讨论】:

  • 这似乎成功了。谢谢。
  • 这里显示的设置器是错误的。它必须调用SetValue(ItemsSourceProperty, value) 而没有别的。详情请见XAML Loading and Dependency Properties
  • 所以setter上的逻辑必须移到回调中?
  • 还有两个笔记。检查 e.NewValuelist 是否为空是多余的。您只能查看list。然后,动态转换 d as AccountSelector 在这里是错误的,因为您希望在 d 中有一个 AccountSelector 实例,而没有别的。其他一切都是错误,应该引发InvalidCastException。所以最好写var s = (AccountSelector)d
  • 终于不用UIPropertyMetadata了。你也可以使用普通的PropertyMetadata
猜你喜欢
  • 2011-12-29
  • 2013-03-26
  • 1970-01-01
  • 1970-01-01
  • 2015-05-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多