Come aumentare gli eventi modificati di proprietà su una proprietà di dipendenza?

OK, quindi ho questo controllo con due proprietà. Uno di questi è DependencyProperty, l’altro è un “alias” per il primo. Quello che devo essere in grado di fare è sollevare l’evento PropertyChanged per il secondo (l’alias) quando viene modificato il primo.

NOTA : Sto usando DependencyObjects, non INotifyPropertyChanged (provato, non ha funzionato perché il mio controllo è un ListView sottoclassato)

qualcosa come questo…..

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

Se stavo usando un INotify, potrei fare così …

 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"); } } } 

dove posso generare eventi PropertyChanged su più proprietà da un setter. Devo essere in grado di fare la stessa cosa, usando solo DependencyProperties.

  1. Implementa INotifyPropertyChanged nella tua class.

  2. Specificare una richiamata nei metadati della proprietà quando si registra la proprietà di dipendenza.

  3. Nella richiamata, aumentare l’evento PropertyChanged.

Aggiungere la richiamata:

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

Raising PropertyChanged nel callback:

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

Mi sono imbattuto in un problema simile in cui ho una proprietà di dipendenza che volevo che la class ascoltasse per modificare gli eventi e prendere i dati relativi da un servizio.

 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"); } 

Penso che l’OP stia facendo la domanda sbagliata. Il codice seguente mostrerà che non è necessario aumentare manualmente l’EVENTO PropertyChanged da una proprietà di dipendenza per ottenere il risultato desiderato. Il modo per farlo è gestire il CALLBACK PropertyChanged sulla proprietà di dipendenza e impostare i valori per le altre proprietà di dipendenza. Quello che segue è un esempio funzionante. Nel codice qui sotto, MyControl ha due proprietà di dipendenza: ActiveTabInt e ActiveTabString. Quando l’utente fa clic sul pulsante sull’host (MainWindow), ActiveTabString viene modificato. Il CALLBACK PropertyChanged sulla proprietà di dipendenza imposta il valore di ActiveTabInt. L’EVENTO PropertyChanged non viene generato manualmente da MyControl.

MainWindow.xaml.cs

 ///  /// Interaction logic for MainWindow.xaml ///  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 Indexmap = new List(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

      

App.xaml

  

Sono d’accordo con Sam e Xaser e ho effettivamente preso questo un po ‘più lontano. Non penso che dovresti implementare l’interfaccia INotifyPropertyChanged in un UserControl … il controllo è già un DependencyObject e quindi viene già fornito con le notifiche. L’aggiunta di INotifyPropertyChanged a DependencyObject è ridondante e “odora” per me.

Quello che ho fatto è implementare entrambe le proprietà come DependencyProperties, come suggerisce Sam, ma poi ha semplicemente avuto il PropertyChangedCallback dalla “prima” proprietà di dipendenza che modifica il valore della proprietà di dipendenza “secondo”. Dal momento che entrambe sono proprietà di dipendenza, entrambe aumenteranno automaticamente le notifiche di cambiamento per tutti gli abbonati interessati (ad es. Associazione dati ecc.)

In questo caso, la proprietà di dipendenza A è la stringa InviteText, che triggers una modifica nella proprietà di dipendenza B, la proprietà Visibility denominata ShowInvite. Questo sarebbe un caso di uso comune se si dispone di un testo che si desidera poter hide completamente in un controllo tramite associazione dati.

  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)); 

Nota Non includo la firma o il costruttore UserControl qui perché non c’è nulla di speciale in loro; non hanno bisogno di sottoclass da INotifyPropertyChanged affatto.

Metto in dubbio la logica di generare un evento PropertyChanged sulla seconda proprietà quando è la prima proprietà che sta cambiando. Se il valore delle seconde proprietà cambia, l’evento PropertyChanged potrebbe essere generato lì.

In ogni caso, la risposta alla tua domanda è che dovresti implementare INotifyPropertyChange. Questa interfaccia contiene l’evento PropertyChanged. L’implementazione di INotifyPropertyChanged consente ad altri codice di sapere che la class ha l’evento PropertyChanged, in modo che il codice possa colbind un gestore. Dopo aver implementato INotifyPropertyChange, il codice che va nella dichiarazione if di OnPropertyChanged è:

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