簡體   English   中英

C#WPF MVVM窗口OnLoad綁定

[英]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中使用MainViewModelApplication.Current將為null。 因此,此代碼將在測試中以NullPointerException結束。

如果要確保已初始化某些內容,則應考慮使用Initialized事件。 但是在調用InitializeComponent之后創建了ViewModel - 我只是將其退出。

暫無
暫無

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

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