簡體   English   中英

INotifyPropertyChanged 和自動屬性

[英]INotifyPropertyChanged and Auto-Properties

有沒有辦法將INotifyPropertyChanged與自動屬性一起使用? 也許是一個屬性或其他東西,對我來說並不明顯。

public string Demo{
    get;set;
}

對我來說,自動屬性將是一件非常實用的事情,但幾乎總是,如果屬性值已更改並且沒有執行此操作的機制,則幾乎總是我必須引發PropertyChanged事件,自動屬性對我來說毫無用處。

在 .NET 4.5 及更高版本中,它可以縮短一些

private int unitsInStock;
public int UnitsInStock
{
    get { return unitsInStock; }
    set { SetProperty(ref unitsInStock, value);}
}

這是你必須自己編碼的東西。 你能得到的最接近的是代碼項目上的這個實現,它使用自定義屬性和面向方面的方法來提供以下語法:

[NotifyPropertyChanged] 
public class AutoWiredSource
{ 
   public double MyProperty { get; set; } 
}

有人曾經在 Microsoft Connect 上提議對 C# 規范進行更改來實現這一點:

class Person : INotifyPropertyChanged
{
    // "notify" is a context keyword, same as "get" and "set"
    public string Name { get; set; notify; }
}

但該提案現已結束。

沒有內置機制可以做到這一點。 PostSharp這樣的東西可能會為你添加這樣的東西(或者 Mark Gravell 的HyperDescriptor ,如果你只是對讓這個數據綁定感知感興趣)。

我首先嘗試使用其他方法:

這些方法有效,但是我仍然不得不混淆模型中所有屬性的訪問器方法,或者使用dynamic對象在編碼時殺死您的自動完成。 還值得一提的是,不幸的是,WinForms 不支持綁定到動態對象。

解決方案

最終我遇到了ReactiveUI.Fody 這是一個使用 Fody 和 ReactiveUI 的簡單易用的解決方案。 我成功地在我的 WPF 項目中使用了它。

它在編譯時編入所需的樣板代碼RaisePropertyChangesObservableAsPropertyHelper

項目依賴

https://github.com/kswoll/ReactiveUI.Fody

我使用 NuGet 在我的項目中安裝了以下包:

<packages>
  <package id="Fody" version="2.0.7" targetFramework="net452" developmentDependency="true" />
  <package id="reactiveui" version="7.4.0" targetFramework="net452" />
  <package id="ReactiveUI.Fody" version="2.2.11" targetFramework="net452" />
  <package id="reactiveui-core" version="7.4.0" targetFramework="net452" />
  <package id="Rx-Core" version="2.2.5" targetFramework="net452" />
  <package id="Rx-Interfaces" version="2.2.5" targetFramework="net452" />
  <package id="Rx-Linq" version="2.2.5" targetFramework="net452" />
  <package id="Rx-Main" version="2.2.5" targetFramework="net452" />
  <package id="Rx-PlatformServices" version="2.2.5" targetFramework="net452" />
  <package id="Rx-XAML" version="2.2.5" targetFramework="net452" />
  <package id="Splat" version="1.6.0" targetFramework="net452" />
</packages>

福迪設置

您需要在項目的頂層創建一個 FodyWeavers.xml 文件,如下所示:

<?xml version="1.0" encoding="utf-8" ?>
<Weavers>
  <ReactiveUI/>
</Weavers>

用法

您只需將 Model 類設置為繼承ReactiveObject並在要通知更改的任何屬性上方添加[Reactive]屬性。

using ReactiveUI;
using ReactiveUI.Fody.Helpers;

namespace name.domain.some{
    class SomeClass : ReactiveObject {
        [Reactive]
        public string SomeProperty { get; set; }
    }
}

大功告成 重建項目並檢查 Visual Studio 中的輸出窗口。 在 Fody 處理帶注釋的模型類並注入適當的樣板代碼時,您應該會看到一些從 Fody 輸出的行。 它應該是這樣的:

在此處輸入圖片說明

更多信息

更多有用的信息可以在這里找到。

INotifyPropertyChanged和 DependencyProperties 確實讓屬性變得不那么有趣。 我發現的最佳解決方案是好的片段。 例如Silverlight contrib項目中的那些

crea7or 的有用答案,最終在我的最新項目中使用了它。 改進它的一種方法是通過這種方式重寫 SetProperty:

protected bool SetProperty<T>(ref T storage, T value, string[] dependentPropertyNames = null, [CallerMemberName] string propertyName = null)
{
    if (Equals(storage, value))
    {
        return false;
    }

    storage = value;
    this.OnPropertyChanged(propertyName);

    if(dependentPropertyNames != null)
    {
        foreach(var dependentPropertyName in dependentPropertyNames)
        {
            OnPropertyChanged(dependentPropertyName);
        }
    }

    return true;
}

它現在允許傳入依賴屬性名稱,允許視圖知道依賴屬性值已更改,即使它不是直接設置的,而是設置了其他屬性的結果。

用法:

private string firstName;
public string FirstName
{
    get { return firstName; }
    set { SetProperty(ref firstName, value, new[] { "FullName" }); }
}

private string lastName;
public string LastName
{
    get { return lastName; }
    set { SetProperty(ref lastName, value, new[] { "FullName" }); }
}

public string FullName
{
    get { return $"{FirstName} {LastName}"; }
}

暫無
暫無

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

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