绑定属性设置器未被调用

时间:2010-02-10 15:31:06

标签: silverlight

我遇到以下情况的问题(为简洁起见,代码剪切)。基本上,当设置了依赖项属性时,我的用户控件属性的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。我是否必须向PropertyMetadata对象添加一个PropertyChange事件来处理这个事件,因为这似乎是很多简单的代码。

3 个答案:

答案 0 :(得分:5)

这就是如何编写需要在set上运行其他代码的Dependency属性: -

 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处理程序,它将依赖项对象转换为正确的类型,然后调用实例方法来警告该更改的实例。

只要通过属性SetValue方法中的Set调用或绑定或任何其他方式更改了基础依赖项属性,就会调用此更改处理程序。

答案 1 :(得分:3)

是的,如果您需要为setter提供额外的逻辑,请始终使用回调。这是Silverlight和WPF中的必须

据我所知,只有在实际使用代码时才会调用Setter。当你进行Binding时,事情就会发生在使用DependencyProperty框架。

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

答案 2 :(得分:1)

DependencyProperty.Register()方法的Last参数采用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);  
}