[英]C# WPF MVVM Window OnLoad Binding
我的代碼背后看起來像這樣......
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new MainWindowViewModel();
}
}
我的ViewModel看起來像這樣......
class MainWindowViewModel : INotifyPropertyChanged
{
public MainWindowViewModel()
{
bool flag = Application.Current.MainWindow.IsInitialized;
if (flag)
{
// Do something...
}
}
我想我的問題是......這是否符合MVVM設計模式? 執行此操作的唯一方法是在wpf中加載窗口時如何觸發命令
我不知道為什么,但我不想使用mvvm-light或任何其他樣板代碼..
從ViewModel訪問UI組件違反了MVVM模式。
Application.Current.MainWindow.IsInitialized
打破了這種模式。
自定義行為更符合MVVM。 所以,我建議你采用你提到的方法作為你問題中的鏈接。
訪問UI組件會破壞ViewModel的可測試性。 你會如何為ViewModel類編寫測試用例? 當您嘗試通過單元測試測試它時, Application.Current
將為null
,並且它將拋出空引用異常。
MVVM的主要動機之一是從業務邏輯中分離UI邏輯,以便可以單獨測試業務邏輯,而無需擔心其視圖的消費者。
沒有樣板代碼,在MVVM中沒有“純粹”的方法可以做到這一點。 一般情況下,你不需要做任何工作來響應你的VM中的VIew - 只是這個概念違反了MVVM,因為你的ViewModel試圖做一些事情來響應View,而事情應該總是以其他方式流動。
在真實場景中,ViewModel根本不應該關心View的狀態 - 除了為View提供數據綁定之外,它應該什么都不做。
大多數時候,當人們嘗試這樣做時,應該盡量避免預先加載數據。 通過將數據加載並直接在 ViewModel中的后台線程上啟動,然后在VM完成時更新VM中的屬性,通常可以更好地處理這種情況。 C#5的async
/ await
語言功能可以用來簡化這一點。
雖然人們普遍認為有一些加載/卸載邏輯是一種模式違規,但有一些用例是必要的。 例如,視圖模型可能需要訂閱某些事件。 如果在卸載時沒有取消訂閱,則可能不會進行垃圾回收,具體取決於訂閱的性質。
什么會打破這種模式是從視圖模型內訪問視圖狀態,例如操縱控制。 視圖模型的作用是將數據公開給視圖,管理加載/卸載行為是此合同的一部分。 知道何時加載視圖模型意味着知道何時公開該數據。
雖然視圖模型不應該關注視圖的狀態,但它必須知道如何在視圖中准備要呈現的數據。 更重要的是,視圖模型是模型和視圖之間的一個層,使它們分離。 換句話說:由於“模型”意味着邏輯,因此“視圖模型”意味着獲取數據的邏輯。 它也是關於何時獲取它/使它可用/等。
您可能需要查看此博客文章 ,該文章提供了一種方便的方法,使視圖模型可以識別加載。 就MVVM純度而言,它不是100%正確,因為它將FrameworkElement
傳遞回視圖模型,但想象我們忽略此參數。
下面的示例代碼基於上面的博客文章,但具有更純的簽名。 您可以在類上實現IViewModel
接口:
public interface IViewModel : INotifyPropertyChanged
{
void Load();
void Unload();
}
然后通過使用附加屬性指示視圖在加載或卸載時調用適當的方法:
ViewModelBehavior.LoadUnload="True"
請注意,最后一行在XAML中占有一席之地 - 視圖是強制執行某種行為的視圖,反之亦然。
你目前正在做的是正確的,這就是它在幕后使用其他框架的方式。
既然你提到了MVVM-Light,我建議你看一下caliburn micro 。 它有非常好的框架來符合MVVM模式。 Caliburn micro可以輕松地將綁定與控件上的事件掛鈎。 只需查看其文檔,它仍然被視為MVVMy ..
特別是因為MVVM主要用於保證易於維護和可測試的代碼,您應該記住,如果在UnitTests中使用MainViewModel
, Application.Current
將為null。 因此,此代碼將在測試中以NullPointerException
結束。
如果要確保已初始化某些內容,則應考慮使用Initialized
事件。 但是在調用InitializeComponent
之后創建了ViewModel
- 我只是將其退出。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.