绑定属性设置器未被调用

4
我对以下情况有问题(为简洁起见,代码已剪切)。基本上,在设置依赖属性时,我的用户控件属性的Setter没有被调用,我需要解决这个问题。
我在View.xaml中有以下代码。
<Filter:Filter x:Name="ProductFilter" PrimaryItemSource="{Binding CarrierProducts}"  />

在 View.xaml.cs 文件中。
    public ProductPricing()
    {
        InitializeComponent();

        ViewModel.Filter.ProductPricing vm = new ViewModel.Filter.ProductPricing();
        this.DataContext = vm;
    }

在我的 ViewModel 中,我公开了一个属性。
    public ObservableCollection<Model.FilterItem> _carrierProducts;
    public ObservableCollection<Model.FilterItem> CarrierProducts
    {
        get
        {
            return _carrierProducts;
        }
        set
        {
            if (_carrierProducts != value)
            {
                _carrierProducts = value;
                RaisePropertyChanged("CarrierProducts");
            }
        }
    }

最后,过滤器用户控件定义如下。
   public static readonly DependencyProperty PrimaryItemSourceProperty =
        DependencyProperty.Register("PrimaryItemSource", typeof(ObservableCollection<Model.FilterItem>), typeof(Filter), new PropertyMetadata(null));

    public ObservableCollection<Model.FilterItem> PrimaryItemSource
    {
        get
        {
            return (ObservableCollection<Model.FilterItem>)GetValue(PrimaryItemSourceProperty);
        }

        set
        {
            SetValue(PrimaryItemSourceProperty, value);

            ComboBox combo = _filters.ElementAt(0);
            FilterSourceChange(combo, value);
        }
    }

由于某些原因,PrimaryItemSource属性被设置了,但Setter没有被调用。我是否需要将PropertyChange事件添加到PropertyMetadata对象中来处理这个问题,因为这似乎对于一个简单的问题来说是很多代码。

我意识到我可以将PropertyChangedCallback添加到元数据中,但我想知道这是否正常? - James Hughes
3个回答

5
这是一个需要在设置时运行额外代码的依赖属性应该编写的方式:-
 public ObservableCollection<Model.FilterItem> PrimaryItemSource
 {
     get { return (ObservableCollection<Model.FilterItem>)GetValue(PrimaryItemSourceProperty); }
     set { SetValue(PrimaryItemSourceProperty , value); }
 }

 public static readonly DependencyProperty PrimaryItemSourceProperty =  
    DependencyProperty.Register(
    "PrimaryItemSource",
    typeof(ObservableCollection<Model.FilterItem>),
    typeof(Filter), new PropertyMetadata(null, OnPrimaryItemSourceChanged));  


 private static void OnPrimaryItemSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
 {
      Filter filter = (Filter)d;
      var oldValue = (ObservableCollection<Model.FilterItem>)e.OldValue;
      var newValue = (ObservableCollection<Model.FilterItem>)e.NewValue;
      filter.OnPrimaryItemSourceChanged(oldValue, newValue);
 }

 protected virtual void OnPrimaryItemSourceChanged(
     ObservableCollection<Model.FilterItem> oldValue,
     ObservableCollection<Model.FilterItem> newValue)
 {
     ComboBox combo = _filters.ElementAt(0);        
     FilterSourceChange(combo, newValue); 
 }

您可以在需要的类中放置一个静态的DependencyPropertyChanged处理程序,该处理程序将对依赖对象进行类型转换,然后调用实例方法来提醒该实例更改。

无论是通过属性Set方法中的SetValue调用还是通过绑定或任何其他方式进行更改,都会调用此更改处理程序。


3

如果您需要为setter添加附加逻辑,则始终使用回调。在Silverlight和WPF中,这是必须的。

据我所知,当您从代码中使用Setter时,它只会被调用一次。当您执行绑定操作时,将使用DependencyProperty框架进行处理。

您还应该将ComboBox combo = ...代码包装到this.Dispatcher.BeginInvoke(() => ... );中,因为这可以确保可视树已初始化。


1
DependencyProperty.Register() 方法的最后一个参数需要传递一个 PropertyMetaData 对象,而你却传递了 null。构造函数的其中一个重载接受一个 PropertyChangedCallback 参数。使用这个重载来定义一个回调函数,在属性被修改时会被调用。
static void PropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    Filter filter = d as Filter;

    ComboBox combo = filter._filters.ElementAt(0);  

    filter.FilterSourceChange(combo, filter.PrimaryItemSource);  
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接