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