[WPF] MVVM 設計模式下全域屬性(Global Property)實作與 UI 數據雙向同步綁定的方法

紀錄一下實作 WPF 下全域屬性的使用操作,主要是解決 MVVM 跨 ViewModel 共用屬性/變數的方法

使用 MVVM 模式開發時,遇到跨不同 ViewModel 都共用到的同一個屬性(或變數),直覺會想到使用 static 修飾詞

但實際實作上後,就會發現要考慮的東西還真多,尤其是要在 UI 上綁定那就真的是一番功夫,這裡把我使用的方法紀錄一下

首先我會在程式專案同一個 namespace 下建立一個類別管理會用到的共用屬性,不在同一個 namespace 的話,之後使用共用屬性要注意是否有引用對應的命名空間喔!

這裡我用一個共用屬性 LoginUser 做例子,並且自己實做屬性變更時的事件通知(這裡取名為 StaticPropertyChanged)

using System;
using System.ComponentModel;

namespace MyProject
{
    public class GlobalData
    {
        public static event EventHandler<PropertyChangedEventArgs> StaticPropertyChanged;
        
        private static string _LoginUser = "";
        public static string LoginUser
        {
            get { return _LoginUser; }
            set
            {
                _LoginUser = value;
                StaticPropertyChanged?.Invoke(null, new PropertyChangedEventArgs(nameof(LoginUser)));
            }
        }
    }
}

上面這部分有兩點要注意

1. 使用 static 靜態修飾詞的屬性只能封裝 static 靜態變數

2. 因為 static 屬性實體化順序較早,所以若要數值變更時同步通知到其他使用到該屬性的控制元件必須自己實做(這是以我另外文章內所使用 MVVM ViewModelBase 來說)

接下來就是把這個共用屬性綁定到 UI 上去了,這裡把屬性值顯示到一個 Page 的 Label 上;如最開頭提醒的,如果共同屬性放在不同命名空間,別忘記引用囉!

<Page x:Class="MyProject.View.StatusBarView"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      
      xmlns:root="clr-namespace:MyProject"
      xmlns:local="clr-namespace:MyProject.View"
      
      mc:Ignorable="d" 
      x:Name="MainView"
      Height="80" Width="200"
      Title="StatusBarView"
      >
    <Page.Resources>
        <root:GlobalData x:Key="Global"/>
    </Page.Resources>
    <Grid>
        <Label Content="{Binding Source={StaticResource Global}, Path=LoginUser}"/>
    </Grid>
</Page>

OK~完成以上的操作後,就可以開始要用到這屬性的 ViewModel 下操作囉~

以下是範例~我是一個屬性 User 來包這個共用屬性 LoginUser~這個 OnPropertyChanged 請參考前文 [WPF] MVVM 軟體架構模式 - 從基礎元件 ViewModelBase 到完成一個基本的範例

public string User
{
    get { return GlobalData.LoginUser; }
    set
    {
        GlobalData.LoginUser = value;
        OnPropertyChanged();
    }
}

public void GetUser()
{
    MessageBox.Show(User);
}

到此就大功告成了!

新增共用屬性時,在 CLR Set 包裝器下別忘記要加上這句,才能實現屬性改變同步通知 UI 的功能!!

StaticPropertyChanged?.Invoke(null, new PropertyChangedEventArgs(nameof(屬姓名)));

完結灑花~XD