如何提高依赖属性上的属性更改事件?

好的,所以我有两个属性的控制。 其中一个是DependencyProperty,另一个是第一个“别名”。 我需要能够做的是提高PropertyChanged事件的第二个(别名),当第一个被改变。

注意 :我正在使用DependencyObjects,而不是INotifyPropertyChanged(试过,没有工作,因为我的控件是一个子分类的ListView)

像这样的东西…..

protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) { base.OnPropertyChanged(e); if (e.Property == MyFirstProperty) { RaiseAnEvent( MySecondProperty ); /// what is the code that would go here? } } 

如果我使用INotify,我可以这样做…

 public string SecondProperty { get { return this.m_IconPath; } } public string IconPath { get { return this.m_IconPath; } set { if (this.m_IconPath != value) { this.m_IconPath = value; this.SendPropertyChanged("IconPath"); this.SendPropertyChanged("SecondProperty"); } } } 

在那里我可以从一个setter提升多个属性的PropertyChanged事件。 我需要能够做同样的事情,只使用DependencyProperties。

  1. 在你的类中实现INotifyPropertyChanged

  2. 注册依赖项属性时,在属性元数据中指定一个callback。

  3. 在callback中,引发PropertyChanged事件。

添加callback:

 public static DependencyProperty FirstProperty = DependencyProperty.Register( "First", typeof(string), typeof(MyType), new FrameworkPropertyMetadata( false, new PropertyChangedCallback(OnFirstPropertyChanged))); 

在callback中提高PropertyChanged

 private static void OnFirstPropertyChanged( DependencyObject sender, DependencyPropertyChangedEventArgs e) { PropertyChangedEventHandler h = PropertyChanged; if (h != null) { h(sender, new PropertyChangedEventArgs("Second")); } } 

我遇到了类似的问题,我有一个依赖项属性,我希望类听侦听更改事件以获取服务中的相关数据。

 public static readonly DependencyProperty CustomerProperty = DependencyProperty.Register("Customer", typeof(Customer), typeof(CustomerDetailView), new PropertyMetadata(OnCustomerChangedCallBack)); public Customer Customer { get { return (Customer)GetValue(CustomerProperty); } set { SetValue(CustomerProperty, value); } } private static void OnCustomerChangedCallBack( DependencyObject sender, DependencyPropertyChangedEventArgs e) { CustomerDetailView c = sender as CustomerDetailView; if (c != null) { c.OnCustomerChanged(); } } protected virtual void OnCustomerChanged() { // Grab related data. // Raises INotifyPropertyChanged.PropertyChanged OnPropertyChanged("Customer"); } 

我想OP是在问错误的问题。 下面的代码将显示没有必要手动引发PropertyChanged EVENT从一个依赖属性来实现所需的结果。 这样做的方式是在依赖项属性上处理PropertyChanged CALLBACK,并为其中的其他依赖项属性设置值。 以下是一个工作示例。 在下面的代码中,MyControl有两个依赖属性 – ActiveTabInt和ActiveTabString。 当用户点击主机上的button(MainWindow)时,ActiveTabString被修改。 依赖项属性上的PropertyChanged CALLBACK设置ActiveTabInt的值。 PropertyChanged EVENT不是由MyControl手动引发的。

MainWindow.xaml.cs

 /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window, INotifyPropertyChanged { public MainWindow() { InitializeComponent(); DataContext = this; ActiveTabString = "zero"; } private string _ActiveTabString; public string ActiveTabString { get { return _ActiveTabString; } set { if (_ActiveTabString != value) { _ActiveTabString = value; RaisePropertyChanged("ActiveTabString"); } } } private int _ActiveTabInt; public int ActiveTabInt { get { return _ActiveTabInt; } set { if (_ActiveTabInt != value) { _ActiveTabInt = value; RaisePropertyChanged("ActiveTabInt"); } } } #region INotifyPropertyChanged implementation public event PropertyChangedEventHandler PropertyChanged; public void RaisePropertyChanged(string propertyName) { if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } #endregion private void Button_Click(object sender, RoutedEventArgs e) { ActiveTabString = (ActiveTabString == "zero") ? "one" : "zero"; } } public class MyControl : Control { public static List<string> Indexmap = new List<string>(new string[] { "zero", "one" }); public string ActiveTabString { get { return (string)GetValue(ActiveTabStringProperty); } set { SetValue(ActiveTabStringProperty, value); } } public static readonly DependencyProperty ActiveTabStringProperty = DependencyProperty.Register( "ActiveTabString", typeof(string), typeof(MyControl), new FrameworkPropertyMetadata( null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, ActiveTabStringChanged)); public int ActiveTabInt { get { return (int)GetValue(ActiveTabIntProperty); } set { SetValue(ActiveTabIntProperty, value); } } public static readonly DependencyProperty ActiveTabIntProperty = DependencyProperty.Register( "ActiveTabInt", typeof(Int32), typeof(MyControl), new FrameworkPropertyMetadata( new Int32(), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault)); static MyControl() { DefaultStyleKeyProperty.OverrideMetadata(typeof(MyControl), new FrameworkPropertyMetadata(typeof(MyControl))); } public override void OnApplyTemplate() { base.OnApplyTemplate(); } private static void ActiveTabStringChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { MyControl thiscontrol = sender as MyControl; if (Indexmap[thiscontrol.ActiveTabInt] != thiscontrol.ActiveTabString) thiscontrol.ActiveTabInt = Indexmap.IndexOf(e.NewValue.ToString()); } } 

MainWindow.xaml

  <StackPanel Orientation="Vertical"> <Button Content="Change Tab Index" Click="Button_Click" Width="110" Height="30"></Button> <local:MyControl x:Name="myControl" ActiveTabInt="{Binding ActiveTabInt, Mode=TwoWay}" ActiveTabString="{Binding ActiveTabString}"></local:MyControl> </StackPanel> 

App.xaml中

 <Style TargetType="local:MyControl"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="local:MyControl"> <TabControl SelectedIndex="{Binding ActiveTabInt, Mode=TwoWay}"> <TabItem Header="Tab Zero"> <TextBlock Text="{Binding ActiveTabInt}"></TextBlock> </TabItem> <TabItem Header="Tab One"> <TextBlock Text="{Binding ActiveTabInt}"></TextBlock> </TabItem> </TabControl> </ControlTemplate> </Setter.Value> </Setter> </Style> 

我同意Sam和Xaser,实际上已经把这个做得更远了。 我不认为你应该在UserControl中实现INotifyPropertyChanged接口…该控件已经是一个DependencyObject,因此已经带有通知。 将INotifyPropertyChanged添加到一个DependencyObject是多余的,对我来说“闻起来”是错误的。

我所做的就是将两个属性都作为DependencyProperties实现,就像Sam所build议的那样,但是只需从“first”依赖项属性改变“second”依赖项属性的值就可以实现PropertyChangedCallback。 由于两者都是依赖属性,两者都会自动将更改通知提交给任何感兴趣的订阅者(例如数据绑定等)

在这种情况下,依赖项属性A是stringInviteText,它触发依赖项属性B中名为ShowInvite的Visibility属性的更改。 如果您想要通过数据绑定将某些文本完全隐藏在控件中,则这将是一个常见用例。

  public string InviteText { get { return (string)GetValue(InviteTextProperty); } set { SetValue(InviteTextProperty, value); } } public static readonly DependencyProperty InviteTextProperty = DependencyProperty.Register("InviteText", typeof(string), typeof(InvitePrompt), new UIPropertyMetadata(String.Empty, OnInviteTextChanged)); private static void OnInviteTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { InvitePrompt prompt = d as InvitePrompt; if (prompt != null) { string text = e.NewValue as String; prompt.ShowInvite = String.IsNullOrWhiteSpace(text) ? Visibility.Collapsed : Visibility.Visible; } } public Visibility ShowInvite { get { return (Visibility)GetValue(ShowInviteProperty); } set { SetValue(ShowInviteProperty, value); } } public static readonly DependencyProperty ShowInviteProperty = DependencyProperty.Register("ShowInvite", typeof(Visibility), typeof(InvitePrompt), new PropertyMetadata(Visibility.Collapsed)); 

注意我没有在这里包含UserControl签名或构造函数,因为它们没有什么特别之处。 他们根本不需要INotifyPropertyChanged的子类。

我怀疑当第一个属性发生变化时,在第二个属性上引发PropertyChanged事件的逻辑。 如果第二个属性值更改,那么PropertyChanged事件可能会在此处引发。

无论如何,你的问题的答案是你应该实现INotifyPropertyChange。 该接口包含PropertyChanged事件。 实现INotifyPropertyChanged让其他代码知道该类有PropertyChanged事件,以便代码可以挂钩处理程序。 在实现INotifyPropertyChange后,OnPropertyChanged的if语句中的代码是:

 if (PropertyChanged != null) PropertyChanged(new PropertyChangedEventArgs("MySecondProperty"));