C# Winform 實(shí)現(xiàn)靜態(tài)變量屬性的值變了,觸發(fā)事件,類似WPF的雙向綁定
在C# WinForms中,雖然沒(méi)有像WPF那樣內(nèi)置的雙向綁定機(jī)制,但你可以通過(guò)事件和屬性封裝來(lái)實(shí)現(xiàn)類似的功能。具體來(lái)說(shuō),你可以在靜態(tài)屬性的set訪問(wèn)器中觸發(fā)一個(gè)自定義事件,然后在需要的地方訂閱這個(gè)事件,以便在屬性值發(fā)生變化時(shí)執(zhí)行相應(yīng)的操作。
全局狀態(tài)的隱患
- 問(wèn)題:靜態(tài)類和靜態(tài)事件引入了全局狀態(tài),這意味著任何代碼都可以訂閱或觸發(fā)這個(gè)事件。這種全局狀態(tài)可能導(dǎo)致代碼難以維護(hù)和調(diào)試,尤其是在大型項(xiàng)目中。
- 風(fēng)險(xiǎn):如果多個(gè)模塊或類訂閱了該事件,事件的觸發(fā)可能會(huì)導(dǎo)致意外的副作用,甚至引發(fā)難以追蹤的 bug。
內(nèi)存泄漏風(fēng)險(xiǎn)
- 靜態(tài)事件的生命周期與應(yīng)用程序域相同,除非顯式取消訂閱,否則訂閱者(尤其是對(duì)象實(shí)例)永遠(yuǎn)不會(huì)被垃圾回收。
- 如果訂閱者沒(méi)有正確取消訂閱,可能會(huì)導(dǎo)致內(nèi)存泄漏。
Form 窗體釋放后,記得取消訂閱
public void MyForm_Closing(object sender, FormClosingEventArgs e)
{
//顯式取消訂閱
GlobalEvents.SomeGlobalEvent -= HandleEvent;
}
//或者
public void Dispose()
{
//顯式取消訂閱
GlobalEvents.SomeGlobalEvent -= HandleEvent;
}
以下是一個(gè)簡(jiǎn)單的示例,展示了如何實(shí)現(xiàn)這一功能:
using System;
using System.Windows.Forms;
public static class MyStaticClass
{
// 定義事件
public static event EventHandler<EventArgs> MyPropertyChanged;
private static string _myProperty;
public static string MyProperty
{
get { return _myProperty; }
set
{
if (_myProperty != value)
{
_myProperty = value;
// 觸發(fā)事件
OnMyPropertyChanged();
}
}
}
// 觸發(fā)事件的方法
private static void OnMyPropertyChanged()
{
MyPropertyChanged?.Invoke(null, EventArgs.Empty);
}
}
public class MyForm : Form
{
private Label myLabel;
public MyForm()
{
myLabel = new Label();
myLabel.Text = "Initial Value";
myLabel.Location = new System.Drawing.Point(10, 10);
this.Controls.Add(myLabel);
// 訂閱事件
MyStaticClass.MyPropertyChanged += MyStaticClass_MyPropertyChanged;
}
// 事件處理程序
private void MyStaticClass_MyPropertyChanged(object sender, EventArgs e)
{
// 當(dāng)屬性值變化時(shí),更新Label的文本
myLabel.Text = MyStaticClass.MyProperty;
}
[STAThread]
public static void Main()
{
Application.EnableVisualStyles();
Application.Run(new MyForm());
}
}
使用示例:
你可以在其他地方修改 MyStaticClass.MyProperty 的值,例如:
MyStaticClass.MyProperty = "New Value";
注意事項(xiàng):
- 由于 MyProperty 是靜態(tài)的,它的值在整個(gè)應(yīng)用程序生命周期內(nèi)是共享的。
- 如果你需要在多個(gè)窗體或控件之間共享狀態(tài),這種方法是有效的。
通過(guò)這種方式,你可以在WinForms中實(shí)現(xiàn)類似WPF的雙向綁定效果。
這里使用的是 EventHandler<TEventArgs> 泛型委托,其中 TEventArgs 是 EventArgs 類型(或派生類型)。這種定義方式已經(jīng)隱式地使用了委托,因此不需要顯式地定義一個(gè)新的委托類型。
如果顯式定義委托,好處是什么?
1. 自定義事件參數(shù):
如果你需要傳遞更多信息(不僅僅是 sender 和 EventArgs),可以定義一個(gè)自定義的事件參數(shù)類,并為其定義一個(gè)專門的委托。
public class MyPropertyChangedEventArgs : EventArgs
{
public string OldValue { get; }
public string NewValue { get; }
public MyPropertyChangedEventArgs(string oldValue, string newValue)
{
OldValue = oldValue;
NewValue = newValue;
}
}
// 定義自定義委托
public delegate void MyPropertyChangedEventHandler(object sender, MyPropertyChangedEventArgs e);
// 使用自定義委托定義事件
public static event MyPropertyChangedEventHandler MyPropertyChanged;
這樣,事件處理程序可以接收到更多信息(如舊值和新值)。
2. 提高代碼可讀性:
顯式定義委托可以讓代碼更具可讀性,尤其是當(dāng)事件的用途非常明確時(shí)。
public delegate void MyPropertyChangedDelegate(string newValue);
public static event MyPropertyChangedDelegate MyPropertyChanged;
這種方式更直觀地表達(dá)了事件的用途。
3.靈活性:
自定義委托可以定義更靈活的參數(shù)列表,而不僅限于 object sender, EventArgs e 的標(biāo)準(zhǔn)模式。
例如,你可以定義一個(gè)沒(méi)有 sender 參數(shù)的事件:
public delegate void MyPropertyChangedDelegate(string newValue);
public static event MyPropertyChangedDelegate MyPropertyChanged;
顯式定義委托
以下是顯式定義委托的完整示例:
using System;
using System.Windows.Forms;
public static class MyStaticClass
{
// 定義自定義委托
public delegate void MyPropertyChangedDelegate(string newValue);
// 定義事件
public static event MyPropertyChangedDelegate MyPropertyChanged;
private static string _myProperty;
public static string MyProperty
{
get { return _myProperty; }
set
{
if (_myProperty != value)
{
string oldValue = _myProperty;
_myProperty = value;
// 觸發(fā)事件
OnMyPropertyChanged(value);
}
}
}
// 觸發(fā)事件的方法
private static void OnMyPropertyChanged(string newValue)
{
MyPropertyChanged?.Invoke(newValue);
}
}
public class MyForm : Form
{
private Label myLabel;
public MyForm()
{
myLabel = new Label();
myLabel.Text = "Initial Value";
myLabel.Location = new System.Drawing.Point(10, 10);
this.Controls.Add(myLabel);
// 訂閱事件
MyStaticClass.MyPropertyChanged += MyStaticClass_MyPropertyChanged;
}
// 事件處理程序
private void MyStaticClass_MyPropertyChanged(string newValue)
{
// 當(dāng)屬性值變化時(shí),更新Label的文本
myLabel.Text = newValue;
}
[STAThread]
public static void Main()
{
Application.EnableVisualStyles();
Application.Run(new MyForm());
}
}
總結(jié)
使用 EventHandler 的好處:
- 簡(jiǎn)單、標(biāo)準(zhǔn)化,適合大多數(shù)場(chǎng)景。
- 符合 .NET 的事件模式(object sender, EventArgs e)。
顯式定義委托的好處:
- 更靈活,可以自定義參數(shù)列表。
- 提高代碼可讀性和表達(dá)力。
- 適合需要傳遞更多信息的場(chǎng)景。
在實(shí)際開發(fā)中,選擇哪種方式取決于具體需求。如果只是簡(jiǎn)單的值變化通知,使用 EventHandler 就足夠了;如果需要更復(fù)雜的事件參數(shù)或更高的靈活性,則可以顯式定義委托。
本文來(lái)自博客園,作者:VipSoft 轉(zhuǎn)載請(qǐng)注明原文鏈接:http://www.rzrgm.cn/vipsoft/p/18702001
浙公網(wǎng)安備 33010602011771號(hào)