NuGet 安裝
安裝 PropertyChanged.Fody NuGet 包並更新 Fody NuGet 包:Install the PropertyChanged.Fody NuGet package and update the Fody NuGet package:
PM> Install-Package Fody
PM> Install-Package PropertyChanged.Fody
這是必需的,因為 NuGet 始終預設為任何依賴項的最舊、最有缺陷的版本。Install-Package Fody
新增到FodyWeavers.xml
新增到FodyWeavers.xml<PropertyChanged/>
<Weavers>
<PropertyChanged/>
</Weavers>
概述
注意:實現 INotifyPropertyChanged
的所有類都將通知程式碼注入到屬性設定器中。
在程式碼之前:
public class Person : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public string GivenNames { get; set; }
public string FamilyName { get; set; }
public string FullName => $"{GivenNames} {FamilyName}";
}
編譯的內容:
public class Person : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
string givenNames;
public string GivenNames
{
get => givenNames;
set
{
if (value != givenNames)
{
givenNames = value;
OnPropertyChanged(InternalEventArgsCache.GivenNames);
OnPropertyChanged(InternalEventArgsCache.FullName);
}
}
}
string familyName;
public string FamilyName
{
get => familyName;
set
{
if (value != familyName)
{
familyName = value;
OnPropertyChanged(InternalEventArgsCache.FamilyName);
OnPropertyChanged(InternalEventArgsCache.FullName);
}
}
}
public string FullName => $"{GivenNames} {FamilyName}";
protected void OnPropertyChanged(PropertyChangedEventArgs eventArgs)
{
PropertyChanged?.Invoke(this, eventArgs);
}
}
internal static class InternalEventArgsCache
{
internal static PropertyChangedEventArgs FamilyName = new PropertyChangedEventArgs("FamilyName");
internal static PropertyChangedEventArgs FullName = new PropertyChangedEventArgs("FullName");
internal static PropertyChangedEventArgs GivenNames = new PropertyChangedEventArgs("GivenNames");
}
(實際注入的型別和方法名稱不同)
程式碼生成器
從版本 4 開始,PropertyChanged.Fody 附帶了一個 C# 程式碼生成器,該生成器可以透過生成 基本實現的樣板直接作為原始碼為您服務。INotifyPropertyChanged
只需將實現或具有屬性的類標記為 和 生成器將新增必要的事件和事件呼叫器:INotifyPropertyChanged
[AddINotifyPropertyChangedInterface]
partial
例如,像這樣的類:
public partial class Class1 : INotifyPropertyChanged
{
public int Property1 { get; set; }
public int Property2 { get; set; }
}
將透過生成器補充以下內容:
public partial class Class1
{
public event PropertyChangedEventHandler? PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string? propertyName = null)
{
OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
}
protected virtual void OnPropertyChanged(PropertyChangedEventArgs eventArgs)
{
PropertyChanged?.Invoke(this, eventArgs);
}
}
- 僅支援類,不支援記錄。
- 對於巢狀類,所有包含類也必須是分部類。
- 程式碼生成器僅在 SDK 樣式的專案中正常工作
程式碼生成器配置
您可以透過專案檔案中的屬性配置程式碼生成器:
<PropertyGroup>
<PropertyChangedAnalyzerConfiguration>
<IsCodeGeneratorDisabled>false</IsCodeGeneratorDisabled>
<EventInvokerName>OnPropertyChanged</EventInvokerName>
</PropertyChangedAnalyzerConfiguration>
</PropertyGroup>
- IsCodeGeneratorDisabled:設定為以關閉程式碼生成器。
true
- EventInvokerName:將事件呼叫程式方法的名稱從更改為收藏夾名稱。
OnPropertyChanged
面向多個框架的 WPF 專案的解決方法:
面向多個框架的 WPF 專案可能會在編譯*_wpftmp.csproj
... error CS0111: Type 'SomeType' already defines a member called 'OnPropertyChanged' with the same parameter types
這可以透過將以下生成目標新增到專案中來解決:
<Target Name="RemoveDuplicateAnalyzers" BeforeTargets="CoreCompile">
<!-- see https://github.com/dotnet/wpf/pull/6680 -->
<RemoveDuplicates Inputs="@(Analyzer)">
<Output
TaskParameter="Filtered"
ItemName="FilteredAnalyzer"/>
</RemoveDuplicates>
<ItemGroup>
<Analyzer Remove="@(Analyzer)" />
<Analyzer Include="@(FilteredAnalyzer)" />
</ItemGroup>
</Target>
筆記
-
依賴屬性 — 在上面的示例中,getter for 依賴於 和 的 getter 。因此,當設定了 or 時,也會為 as 提出。可以使用源屬性上的
AlsoNotifyFor
屬性或目標屬性上的DependsOn
屬性手動配置此行為。FullName
GivenName
FamilyName
GivenName
FamilyName
PropertyChanged
FullName
-
攔截通知呼叫
- 全域性攔截
- 類級攔截 — 僅當類上沒有此類現有方法時,才會注入該方法;如果有這樣的方法,那麼對該方法的呼叫將被注入到設定器中 - 請參閱此處。
OnPropertyChanged
- 屬性級攔截 — 對於給定屬性,如果存在 形式為 的方法,則該方法將被呼叫 — 請參閱此處。
On<PropertyName>Changed
-
要獲取 before/after 值,請對 / 使用以下簽名:
OnPropertyChanged
On<PropertyName>Changed
public void OnPropertyChanged(string propertyName, object before, object after)
-
若要防止特定類進行通知呼叫注入,請使用
DoNotNotify
屬性。 -
若要僅將重寫範圍限定為特定類,而不限於整個程式集,可以使用
FilterType
屬性。這會將常規行為從“選擇退出”更改為“選擇加入”。例:。該字串被解釋為正規表示式,您可以使用多個篩選器。如果任何過濾器匹配,則將編織一個類。[assembly: PropertyChanged.FilterType("My.Specific.OptIn.Namespace.")]
-
可以使用
AddINotifyPropertyChangedInterfaceAttribute
屬性為特定類自動實現介面。提出有關“此屬性的行為不符合預期”的問題將導致 RTFM 並關閉問題。INotifyPropertyChanged
- 對於部分方法,這將透過程式碼生成器完成,因此在編譯時可以使用實現。
-
行為是透過屬性或
Weavers.xml
檔案中的選項配置的。
有關詳細資訊,請參閱 Wiki 頁面。