簡體   English   中英

實際未更改時如何觸發屬性更改事件

[英]How to fire Property Changed Event when it's not actually changing

所以我有一個模型,其中包含2個變量,一個List和一個DateTime。 在我的UserControl中,我具有DependencyProperty,並且還定義了PropertyChangedCallback。

public static readonly DependencyProperty MyProperty = DependencyProperty.Register("My", typeof(List<MyContainer>), typeof(UC), new FrameworkPropertyMetadata(null, new PropertyChangedCallback(OnMyProperty)));

public List<MyContainer> My
{
    get
    {
        return GetValue(MyProperty) as List<MyContainer>;
    }
    set
    {
        SetValue(MyProperty, value);
    }
}
private static void OnMyProperty(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    UC control = d as UC;
    //do stuff
}

在我的表單上有一個按鈕,用於對另一個模型變量(在DateTime上)進行更改。

private void Date_Click(object sender, RoutedEventArgs e)
{
    MyModel model = DataContext as MyModel;
    if (model != null)
    {
        model.Date = model.Date.AddDays(1);
    }
}

最后是我的模型。

public class MyModel : INotifyPropertyChanged
{
    private List<MyContainer> _My;
    private DateTime _Date;

    public MyModel()
    {
        _Date = DateTime.Now.Date;
        _My = new List<MyContainer>();
    }

    public List<MyContainer> My
    {
        get
        {
            return _My;
        }
        set
        {
            _My = value;
            OnPropertyChanged("My");
        }
    }

    public DateTime Date
    {
        get
        {
            return _Date;
        }
        set
        {
            _Date = value;
            OnPropertyChanged("Date");
            OnPropertyChanged("My");
        }
    }

    #region INotifyPropertyChanged
    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
    #endregion
}

XAML聲明如下。

<local:UC My="{Binding My}" />

所以我的問題是,在我點擊運行后,它會觸發一次OnMyProperty,然后如果我按下按鈕,它將很好地更改DateTime屬性,但是OnMyProperty回調不會再次觸發。 但是我注意到如果我像這樣修改我的模型

public DateTime Date
{
    get
    {
       return _Date;
    }
    set
    {
        _Date = value;
        _My = new List<MyContainer>(_My); //added
        OnPropertyChanged("Date");
        OnPropertyChanged("My");
    }
}

現在每次按下按鈕時都會觸發它。 如果不進行修改,如何觸發第二種行為?

設置DependencyProperty的值后,它首先檢查新值是否與舊值不同。 僅在這種情況下,才調用您在該DependencyProperty注冊的PropertyChangedCallback方法。 因此,名稱Property Changed很有意義。

在您(未修改)的情況下,您甚至都不會嘗試更改My (僅Date )。 因此,沒有理由提高回調函數。

答案是您幾乎肯定不需要這樣做。 當您詢問有關如何使框架執行其確實不希望執行的操作的問題時,請始終說出為什么您認為需要執行此操作 很有可能其他人已經在使用一個更簡單的答案。

您綁定到控件的唯一東西是My 因此,如果My尚未更改,則控件的狀態不應更改。 如果你想控制的狀態改變時, Date的變化,結合Date到控制的某些屬性。 控件應該從任何視圖模型獲取信息的唯一方法是將其依賴項屬性之一綁定到視圖模型的屬性。

該控件永遠不應該知道或關心誰或什么為其屬性提供值。 它僅應知道已賦予的屬性值就能夠執行其工作。

如果My的內容已更改-您添加了一個項目或刪除了一個項目-則控件無法知道這一點,因為您拒絕告訴它。 您只是在告訴它有一個新列表。 它檢查,發現它仍然有相同的舊列表,並忽略了您。 您的viewmodel的My屬性應該是ObservableCollection ,因為當您添加或刪除集合中的項目時,它將通知控件。

如果您想要在UI中顯示項目時更改其屬性,則項目本身(您的MyContainer類)也必須實現INofityPropertyChanged

您控件上的依賴項屬性My的類型不能為List<T> 它可能應該是object類型,就像ItemsControl.ItemsSource一樣。 然后,您的控件模板可以在知道如何使用它的ItemsControl顯示它。 如果如上所述將ObservableCollection綁定到它,則ItemsControl將自動更新。 OnMyProperty ,您的控件類還可以檢查它是否也是可觀察的集合:

private static void OnMyProperty(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    UC control = d as UC;

    if (e.NewValue is INotifyCollectionChanged)
    {
        (e.NewValue as INotifyCollectionChanged).CollectionChanged +=
            (s, ecc) => {
                //  Do stuff with UC and ecc.NewItems, ecc.OldItems, etc.
            };
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM