簡體   English   中英

如何在初始化控件時阻止PropertyChanged觸發

[英]How to prevent PropertyChanged from firing while controls are being initialized

這個問題已經引起了一段時間的麻煩,並且阻止了項目的進展。 考慮一個WPF XAML表單,其中包含綁定到ViewModel的控件。 (我正在使用Caliburn.Micro MVVM框架和Entity Framework來獲取數據)。 shell調用Initialize()方法從數據庫加載表單的數據並設置PropertyChanged事件處理程序。 有一個IsDirty標志,用於跟蹤表單中是否有更改的數據。 有一個“保存”按鈕綁定到IsDirty屬性,以便在數據更改時啟用它。

// Sample code; forms have many controls....

// this is the property that the controls are bound to
public Entity BoundData { get; set; }

public void Initialize()
{
    // this is an example line where I query the database from the Entity Framework ObjectContext...
    BoundData = objectContext.DataTable.Where(entity => entity.ID == 1).SingleOrDefault();

    // this is to cause the form bindings to retrieve data from the BoundData entity
    NotifyOfPropertyChange("BoundData");

    // wire up the PropertyChanged event handler
    BoundData.PropertyChanged += BoundData_PropertyChanged;

    IsDirty = false;
}

void BoundData_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    IsDirty = true;
}

// implementation of the IsDirty flag
public bool IsDirty
{
    get
    {
        return _isDirty;
    }
    set
    {
        _isDirty = value;
        NotifyOfPropertyChange("IsDirty");
    }
}

問題是,由於在Initialize()方法完成后從數據庫初始化表單,因此BoundData_PropertyChangedBoundData_PropertyChanged事件處理程序。 因此, IsDirty標志設置為true,並且啟用了“保存”按鈕,即使表單剛剛加載且用戶沒有更改任何內容。 我錯過了什么? 當然這是一個常見的問題,但我一直無法找到一個好的解決方案。 這是我的第一個MVVM項目,所以我完全有可能錯過一些基本概念。

更新:為了澄清,我認為問題是我需要能夠掛鈎一個事件或回調,當所有綁定都完成更新時將觸發,因此我可以連接PropertyChanged事件處理程序。

您可以做的一件事可能有幫助,就是設置觸發更改的屬性,如下所示:

    public virtual bool Prop1
    {
       get
       {
            return _prop1;
       }
       set
       {
            if (_prop1 != value)
            {
                _prop1 = value;
                NotifyOfPropertyChange("IsDirty");
            }
       }

這樣,只有在實際更改了值時才會觸發事件,而不僅僅是冗余設置。 這當然假設在您的情況下該值實際上沒有變化。

我建議你設計一個通用的方法調用。 就像ValueChanged事件處理程序(自定義事件處理程序),它反過來調用BoundData_PropertyChanged。 這意味着,只要控件發生更改,就可以調用此ValueChanged方法/處理程序。

例如

    void ValueChanged(object sender, EventArgs e)
    {
    BoundData_PropertyChanged();
    }

   textBox.TextChanged += new System.EventHandler(ValueChanged);

語法可能不准確,但你可以猜到我在這里提出的建議。

這個解決方案可能不是絕對可靠的,但它在我使用的有限測試用例中對我有用。

在第一次輸入時,EntityKey值將為null。 檢查一下。

/// <summary>
/// Log the invoice status change
/// </summary>
/// <param name="value">The value that the invoice status is changing to</param>
partial void OnInvoiceStatusValueChanging(string value)
{
    var newStatus = ConvertInvoiceStatus(value);
    if (this.EntityKey != null && InvoiceStatus != newStatus)
    {
        AddNewNote(string.Format("Invoice status changing from [{0}] to [{1}]", InvoiceStatus.GetDescription(), newStatus.GetDescription()));
    }
}

/// <summary>
/// Log the invoice status change
/// </summary>
partial void OnInvoiceStatusValueChanged()
{
    if (this.EntityKey != null)
        AddNewNote(string.Format("Invoice status changed to [{0}]", InvoiceStatus.GetDescription()));
}

我知道這個問題很古老,但我遇到了同樣的問題,很難搞清楚。 我是WPF / MVVM的新手,可能不知道谷歌或者問的正確的事情。 這是我的解決方案。 希望它可以幫助某人。

我的IsDirty標志幾乎與原帖中的標志相同。 唯一的區別是我在視圖完成渲染時添加了一個命令將其重置為false。 當呈現/實例化View時 ,基本思想來自Notify ViewModel

在視圖中觸發Loaded事件:

<UserControl x:Class="MyUserControl"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity">
<i:Interaction.Triggers>
    <i:EventTrigger EventName="Loaded">
        <i:InvokeCommandAction Command="{Binding Path=OnLoadedCommand}"/>
    </i:EventTrigger>
</i:Interaction.Triggers>

然后在視圖模型中,在事件觸發時將IsDirty標志設置為false。

public ICommand OnLoadedCommand { get; private set; }

// Constructor
public MyUserControlViewModel()
{
    OnLoadedCommand = new DelegateCommand(OnLoaded);
}

public void OnLoaded()
{
  // Ignore any PropertyChanged events that fire 
  // before the UserControl is rendered.  
   IsDirty = false; 
}

暫無
暫無

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

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