[WPF] MVVM 設計模式下切換頁面(Page)實作

使用 MVVM 設計模式時,實作切換頁面(Page)的方法

網上搜一搜有關『WPF 切換頁面』就會發現非常多各方大大提供教學(感謝在心中~),大都是使用 WinForm 方式實作

如何在 MVVM 模式下實作教學就真的不多了……這次就把我的作法整理如下,話不多說直接上 code 說明~

延續我前一篇 [WPF] MVVM 設計模式下全域屬性(Global Property)實作與 UI 數據雙向同步綁定的方法 的方法先在全域屬性的類別中加入以下程式碼

private const string InitMainActivePageName = "StartPageView";
private static string _MainActivePageName = InitMainActivePageName;
public static string MainActivePageName
{
    get { return _MainActivePageName; }
    set
    {
        if ((value == null) || (value == ""))
        {
            MainActivePage = new Uri(@"../View/" + InitMainActivePageName + ".xaml", UriKind.Relative);
            _MainActivePageName = InitMainActivePageName;
        }
        else
        {
            try
            {
                MainActivePage = new Uri(@"../View/" + value + ".xaml", UriKind.Relative);
                _MainActivePageName = value;
            }
            catch
            {
                MainActivePage = new Uri(@"../View/" + InitMainActivePageName + ".xaml", UriKind.Relative);
                _MainActivePageName = InitMainActivePageName;
            }
        }
        
        StaticPropertyChanged?.Invoke(null, new PropertyChangedEventArgs(nameof(MainActivePageName)));
    }
}
private static Uri _MainActivePage = new Uri(@"../View/" + InitMainActivePageName + ".xaml", UriKind.Relative);
public static Uri MainActivePage
{
    get { return _MainActivePage; }
    set
    {
        _MainActivePage = value;
        StaticPropertyChanged?.Invoke(null, new PropertyChangedEventArgs(nameof(MainActivePage)));
    }
}

設計想法是改變 MainActivePageName 這個 string 屬性聯動改變 MainActivePage 這個 Uri 屬性

話句話說就是前端 UI 的 View 的 Frame 就綁定 MainActivePage,而 ViewModel 透過改變 MainActivePageName 就可以達到切換到對應的 Page 的 View

要注意的是 MainActivePageName 是各別 Page 的 XXXView.xaml,不用打上 .xaml,因為上面已經組好這部分的字串,這部分可以自行修改成自己習慣的方式

另外是我習慣把這個 GlobalData 放在專案根目錄 Root 下,View 放在另外創建的 View 目錄下,所以會開頭組一個 "../View/" 這個字串!

首先在主視窗加入一個 Frame 控制元件來做 Page 的容器,程式碼如下

<Window ...
        xmlns:root="clr-namespace:MyProject"
        ...>
    <Window.Resources>
        <root:GlobalData x:Key="Global"/>
    </Window.Resources>

    <Grid>
        <Frame Source="{Binding Source={StaticResource Global}, Path=MainActivePage}" NavigationUIVisibility="Hidden"/>
    </Grid>
</Window>

到這裡開始另外創三個 Page 分別為 StartPageView / NextPageView / LastPageView,分別程式碼如下

StartPageView 的 View 部分加入一個按鈕

<Button Width="120" Height="28" FontSize="18" Margin="40, 60, 0, 0"
        Content="Switch to NextPage" Click="NextPage_Click"></Button>

StartPageView 的 Code-Behind 部分

private void NextPage_Click(object sender, RoutedEventArgs e)
{
    GlobalData.MainActivePageName0 = "NextPageView";
}

NextPageView 的 View 部分加入兩個按鈕

<Button Width="120" Height="36" FontSize="18" Margin="40, 60, 0, 0"
        Content="Switch to LastPage" Click="LastPage_Click"></Button>
<Button Width="120" Height="36" FontSize="18" Margin="40, 60, 0, 0"
        Content="Switch to StartPage" Click="StartPage_Click"></Button>

NextPageView 的 Code-Behind 部分

private void LastPage_Click(object sender, RoutedEventArgs e)
{
    GlobalData.MainActivePageName = "LastPageView";
}

private void StartPage_Click(object sender, RoutedEventArgs e)
{
    GlobalData.MainActivePageName = "StartPageView";
}

LastPageView 的 View 部分加入兩個按鈕

<Button Width="120" Height="36" FontSize="18" Margin="40, 60, 0, 0"
        Content="Switch to StartPage" Click="StartPage_Click"></Button>
<Button Width="120" Height="36" FontSize="18" Margin="40, 60, 0, 0"
        Content="Switch to NextPage" Click="NextPage_Click"></Button>

LastPageView 的 Code-Behind 部分

private void StartPage_Click(object sender, RoutedEventArgs e)
{
    GlobalData.MainActivePageName = "StartPageView";
}

private void NextPage_Click(object sender, RoutedEventArgs e)
{
    GlobalData.MainActivePageName = "NextPageView";
}

這部分只是示範如何使用,先用 WinForm 樣式呼叫事件處理,請自行改成 RelayCommand,請參考 [WPF] MVVM 軟體架構模式 - 透過 RelayCommand 綁定方法 (無參數型)

只要前置處理做好,後續就方便切換頁面,只要改變對應 Page 的檔案名就可以切換了!

另外提一下,建議全域屬性 Uri 可以加入一些錯誤處理避免開發過程中不小心打錯 Page 名或是綁定到空 Page 造成程式錯誤的問題!!

完結灑花~XD