一、MVVM概述
MVVM是Model-View-ViewModel的簡寫,主要目的是為了解耦視圖(View)和模型(Model)。
MVVM結構如下:

public class ViewModelLocator { /// <summary> /// Initializes a new instance of the ViewModelLocator class. /// </summary> public ViewModelLocator() { ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default); ////if (ViewModelBase.IsInDesignModeStatic) ////{ //// // Create design time view services and models //// SimpleIoc.Default.Register<IDataService, DesignDataService>(); ////} ////else ////{ //// // Create run time view services and models //// SimpleIoc.Default.Register<IDataService, DataService>(); ////} SimpleIoc.Default.Register<MainViewModel>(); //容器在這里注冊了MainViewModel類 } public MainViewModel Main { get { return ServiceLocator.Current.GetInstance<MainViewModel>();//容器獲取MainViewModel類 } } public static void Cleanup() { // TODO Clear the ViewModels } }
在構造函數中,創建了一個SimpleIoc類型的單實例,用於注冊ViewModel,然后用ServiceLocator對這個SimpleIoc類型的單實例進行包裹,方便統一管理。
觀察App.xaml文件,我們會發現ViewModelLocator類被生成資源字典並加入到了全局資源,所以每次App初始化的時候,就會去初始化ViewModelLocator類。
<Application x:Class="MvvmLightDemo.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:MvvmLightDemo" StartupUri="MainWindow.xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" d1p1:Ignorable="d" xmlns:d1p1="http://schemas.openxmlformats.org/markup-compatibility/2006"> <Application.Resources> <ResourceDictionary> <vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" xmlns:vm="clr-namespace:MvvmLightDemo.ViewModel" /> </ResourceDictionary> </Application.Resources> </Application>
ViewModel文件分析:類繼承了ViewModelBase
public class MainViewModel : ViewModelBase { /// <summary> /// Initializes a new instance of the MainViewModel class. /// </summary> public MainViewModel() { if (IsInDesignMode) { // Code runs in Blend --> create design time data. this.MyProperty = "Hello 123![單獨]"; } else { this.MyProperty = "你好 456!"; // Code runs "for real" } } private string myVar; public string MyProperty { get { return myVar; } set { myVar = value; this.RaisePropertyChanged(); } //this.RaisePropertyChanged()觸發界面更改 } private int _value; public int Value { get { return _value; } set { Set<int>(ref _value, value); }//Set里面已經實現了RaisePropertyChanged } }
四、MVVMLight命令RelayCommand
在MVVM Light框架中,主要通過命令綁定來進行事件的處理。
WPF中,命令是通過實現 ICommand 接口創建的。 ICommand 公開了兩個方法(Execute 及 CanExecute)和一個事件(CanExecuteChanged)。
在MVVM Light框架中,RelayCommand類實現了ICommand 接口,用於完成命令綁定。
通過RelayCommand類的構造函數傳入Action類型的Execute委托和Func<bool>類型的CanExecute委托,CanExecute委托用於表示當前命令是否可以執行,Execute委托則表示執行當前命令對應的方法。
通過命令綁定,解耦了View和ViewModel的行為交互,將視圖的顯示和業務邏輯分開。比如我們對界面上的某個按鈕進行命令綁定,當點擊按鈕的時候,實際上進行操作是在對應的ViewModel下的所綁定的方法中執行的。
RelayCommand包含帶參數跟不帶參數的,帶參數的就用泛型RelayCommand<T>對象
1、帶一個參數的命令綁定
代碼片段如下:
<StackPanel> <GroupBox Header="帶string類型參數的命令" BorderBrush="#FF11519C" BorderThickness="1" FontSize="16" Foreground="#FFCDAA0C" Margin="2"> <StackPanel> <StackPanel Orientation="Horizontal"> <Label Content="UserList:" VerticalContentAlignment="Center" FontSize="20" ></Label> <Label Content="{Binding Path=UserList,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" FontSize="20" /> </StackPanel> <StackPanel Orientation="Horizontal"> <Label Content="UserName:" VerticalContentAlignment="Center" FontSize="20" ></Label> <TextBox Width="200" Name="tbUser"></TextBox> <Button Content="AddUser" Command="{Binding AddUserCommand}" CommandParameter="{Binding ElementName=tbUser,Path=Text}"></Button> <CheckBox Content="IsCanAdd" VerticalAlignment="Center" FontSize="16" IsChecked="{Binding IsCanAddUser, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></CheckBox> </StackPanel> </StackPanel> </GroupBox> </StackPanel>
private RelayCommand<string> addUserCommand; public RelayCommand<string> AddUserCommand { get { if (addUserCommand == null) { addUserCommand = new RelayCommand<string>(AddUser, (string p) => { return IsCanAddUser; }); } return addUserCommand; } set { addUserCommand = value; } } private void AddUser(string par) { UserList = UserList + " " + par; }
2、帶多個參數的命令綁定
給命令傳遞多個參數,建議使用以下方式:
使用MultiBinding將多綁定的各個值轉換成我們所需的對象或者實例模型,再傳遞給ViewModel中的命令。
代碼片段如下:
<Window x:Class="MvvmLightDemo1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:MvvmLightDemo1" xmlns:cvt="clr-namespace:MvvmLightDemo1.Converter" xmlns:mvvm="http://www.galasoft.ch/mvvmlight" xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" mc:Ignorable="d" Title="MVVMLIghtDemo1" Height="500" Width="700" > <Window.Resources> <cvt:UserInfoConverter x:Key="userInfoConverter"></cvt:UserInfoConverter> </Window.Resources> <Window.DataContext> <Binding Path="Main" Source="{StaticResource Locator}"></Binding> </Window.DataContext> <StackPanel> <StackPanel> <GroupBox Header="帶string類型參數的命令" BorderBrush="#FF11519C" BorderThickness="1" FontSize="16" Foreground="#FFCDAA0C" Margin="2"> <StackPanel> <StackPanel Orientation="Horizontal"> <Label Content="UserList:" VerticalContentAlignment="Center" FontSize="20" ></Label> <Label Content="{Binding Path=UserList,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" FontSize="20" /> </StackPanel> <StackPanel Orientation="Horizontal"> <Label Content="UserName:" VerticalContentAlignment="Center" FontSize="20" ></Label> <TextBox Width="200" Name="tbUser"></TextBox> <Button Content="AddUser" Command="{Binding AddUserCommand}" CommandParameter="{Binding ElementName=tbUser,Path=Text}"></Button> <CheckBox Content="IsCanAdd" VerticalAlignment="Center" FontSize="16" IsChecked="{Binding IsCanAddUser, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></CheckBox> </StackPanel> </StackPanel> </GroupBox> </StackPanel> <StackPanel> <GroupBox Header="帶對象類型參數的命令" BorderBrush="#FF11519C" BorderThickness="1" FontSize="16" Foreground="#FF127C0D" Margin="2"> <StackPanel> <StackPanel Orientation="Horizontal"> <Label Content="UserName:" FontSize="16" ></Label> <TextBox Width="200" Name="tbxUser" FontSize="16" /> <Label Content="Password:" FontSize="16" ></Label> <TextBox Width="200" Name="tbxPwd" FontSize="16" /> <Button Content="AddUser" Command="{Binding AddUserCommandWithObjPar}"> <Button.CommandParameter> <MultiBinding Converter="{StaticResource userInfoConverter}"> <Binding ElementName="tbxUser" Path="Text"/> <Binding ElementName="tbxPwd" Path="Text"/> </MultiBinding> </Button.CommandParameter> </Button> </StackPanel> <StackPanel Orientation="Horizontal"> <Label Content="Parameter:" FontSize="16" ></Label> <Label Content="{Binding ObjParameter}" FontSize="16" ></Label> </StackPanel> </StackPanel> </GroupBox> </StackPanel> <StackPanel> <GroupBox Header="事件轉命令" BorderBrush="#FF11519C" BorderThickness="1" FontSize="16" Foreground="#FFCDAA0C" Margin="2"> <StackPanel> <StackPanel> <ListBox x:Name="lb" ItemsSource="{Binding ListBoxData}" BorderThickness="0" SelectedIndex="{Binding SelectIndex}" > <i:Interaction.Triggers> <i:EventTrigger EventName="SelectionChanged"> <mvvm:EventToCommand Command="{Binding SelectionChangedCommand}"/> </i:EventTrigger> </i:Interaction.Triggers> <ListBox.ItemsPanel> <ItemsPanelTemplate> <WrapPanel Width="{Binding ActualWidth,RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}"/> </ItemsPanelTemplate> </ListBox.ItemsPanel> <ListBox.ItemTemplate> <DataTemplate> <Border BorderBrush="AntiqueWhite" BorderThickness="1"> <StackPanel Margin="2"> <Image Source="{Binding Img}" Width="96" Height="96"/> <TextBlock HorizontalAlignment="Center" Text="{Binding Info}"/> </StackPanel> </Border> </DataTemplate> </ListBox.ItemTemplate> </ListBox> <Label Content="您選擇的是:" FontSize="16" ></Label> <Label Content="{Binding Path=SelResult,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" FontSize="16" /> </StackPanel> </StackPanel> </GroupBox> </StackPanel> </StackPanel> </Window>
using MvvmLightDemo1.ViewModel; using System; using System.Linq; using System.Windows.Data; namespace MvvmLightDemo1.Converter { public class UserInfoConverter: IMultiValueConverter { public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) { if (!values.Cast<string>().Any(text => string.IsNullOrEmpty(text)) && values.Count() == 2) { UserModel userModel = new UserModel() { UserName = values[0].ToString(), PassWord = values[1].ToString()}; return userModel; } return null; } public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } } }
private RelayCommand<UserModel> addUserCommandWithObjPar; public RelayCommand<UserModel> AddUserCommandWithObjPar { get { if (addUserCommandWithObjPar == null) { addUserCommandWithObjPar = new RelayCommand<UserModel>(AddUserWithObjPar); } return addUserCommandWithObjPar; } set { addUserCommandWithObjPar = value; } } private void AddUserWithObjPar(UserModel par) { ObjParameter = "UserName: "+ par.UserName + " Password: " + par.PassWord; }
在WPF中,並不是所有控件都有Command,例如TextBox,那么當文本改變,我們需要處理一些邏輯,這些邏輯在ViewModel中,沒有Command如何綁定呢?
這個時候我們就用到EventToCommand,事件轉命令,可以將一些事件例如TextChanged,Checked等事件轉換成命令的方式。
接下來我們就以ListBox為例子,來看看具體的實例:
View代碼:(這邊聲明了i特性和mvvm特性,一個是為了擁有觸發器和行為附加屬性的能力,當事件觸發時,會去調用相應的命令,EventName代表觸發的事件名稱;一個是為了使用MVVMLight中 EventToCommand功能。)
這邊就是當ListBox執行SelectionChanged事件的時候,會相應去執行ViewModel中 SelectionChangedCommand命令。
代碼片段如下:
<Window x:Class="MvvmLightDemo1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:MvvmLightDemo1" xmlns:cvt="clr-namespace:MvvmLightDemo1.Converter" xmlns:mvvm="http://www.galasoft.ch/mvvmlight" xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" mc:Ignorable="d" Title="MVVMLIghtDemo1" Height="500" Width="700" > <Window.Resources> <cvt:UserInfoConverter x:Key="userInfoConverter"></cvt:UserInfoConverter> </Window.Resources> <Window.DataContext> <Binding Path="Main" Source="{StaticResource Locator}"></Binding> </Window.DataContext> <StackPanel> <StackPanel> <GroupBox Header="帶string類型參數的命令" BorderBrush="#FF11519C" BorderThickness="1" FontSize="16" Foreground="#FFCDAA0C" Margin="2"> <StackPanel> <StackPanel Orientation="Horizontal"> <Label Content="UserList:" VerticalContentAlignment="Center" FontSize="20" ></Label> <Label Content="{Binding Path=UserList,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" FontSize="20" /> </StackPanel> <StackPanel Orientation="Horizontal"> <Label Content="UserName:" VerticalContentAlignment="Center" FontSize="20" ></Label> <TextBox Width="200" Name="tbUser"></TextBox> <Button Content="AddUser" Command="{Binding AddUserCommand}" CommandParameter="{Binding ElementName=tbUser,Path=Text}"></Button> <CheckBox Content="IsCanAdd" VerticalAlignment="Center" FontSize="16" IsChecked="{Binding IsCanAddUser, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></CheckBox> </StackPanel> </StackPanel> </GroupBox> </StackPanel> <StackPanel> <GroupBox Header="帶對象類型參數的命令" BorderBrush="#FF11519C" BorderThickness="1" FontSize="16" Foreground="#FF127C0D" Margin="2"> <StackPanel> <StackPanel Orientation="Horizontal"> <Label Content="UserName:" FontSize="16" ></Label> <TextBox Width="200" Name="tbxUser" FontSize="16" /> <Label Content="Password:" FontSize="16" ></Label> <TextBox Width="200" Name="tbxPwd" FontSize="16" /> <Button Content="AddUser" Command="{Binding AddUserCommandWithObjPar}"> <Button.CommandParameter> <MultiBinding Converter="{StaticResource userInfoConverter}"> <Binding ElementName="tbxUser" Path="Text"/> <Binding ElementName="tbxPwd" Path="Text"/> </MultiBinding> </Button.CommandParameter> </Button> </StackPanel> <StackPanel Orientation="Horizontal"> <Label Content="Parameter:" FontSize="16" ></Label> <Label Content="{Binding ObjParameter}" FontSize="16" ></Label> </StackPanel> </StackPanel> </GroupBox> </StackPanel> <StackPanel> <GroupBox Header="事件轉命令" BorderBrush="#FF11519C" BorderThickness="1" FontSize="16" Foreground="#FFCDAA0C" Margin="2"> <StackPanel> <StackPanel> <ListBox x:Name="lb" ItemsSource="{Binding ListBoxData}" BorderThickness="0" SelectedIndex="{Binding SelectIndex}" > <i:Interaction.Triggers> <i:EventTrigger EventName="SelectionChanged"> <mvvm:EventToCommand Command="{Binding SelectionChangedCommand}"/> </i:EventTrigger> </i:Interaction.Triggers> <ListBox.ItemsPanel> <ItemsPanelTemplate> <WrapPanel Width="{Binding ActualWidth,RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}"/> </ItemsPanelTemplate> </ListBox.ItemsPanel> <ListBox.ItemTemplate> <DataTemplate> <Border BorderBrush="AntiqueWhite" BorderThickness="1"> <StackPanel Margin="2"> <Image Source="{Binding Img}" Width="96" Height="96"/> <TextBlock HorizontalAlignment="Center" Text="{Binding Info}"/> </StackPanel> </Border> </DataTemplate> </ListBox.ItemTemplate> </ListBox> <Label Content="您選擇的是:" FontSize="16" ></Label> <Label Content="{Binding Path=SelResult,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" FontSize="16" /> </StackPanel> </StackPanel> </GroupBox> </StackPanel>
<StackPanel>
<GroupBox Header="帶事件本身參數的命令" BorderBrush="#FF11519C" BorderThickness="1" FontSize="16" Foreground="#FF127C0D" Margin="2">
<StackPanel Orientation="Horizontal">
<Button Content="拖拽上傳文件" AllowDrop="True">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Drop">
<mvvm:EventToCommand PassEventArgsToCommand="True" Command="{Binding DropCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
<Label Content="FilePath:" FontSize="16" ></Label>
<Label Content="{Binding DraggedFilePath}" FontSize="16" ></Label>
</StackPanel>
</GroupBox>
</StackPanel>
</StackPanel> </Window>
五、MVVMLight消息Messenger
Messeger是信使的意思,顧名思義,他的目是用於View和ViewModel 以及 ViewModel和ViewModel 之間的消息通知和接收。Messenger類用於應用程序的通信,接受者只能接受注冊的消息類型,另外目標類型可以被指定,用Send<TMessage, TTarget>(TMessage message)實現,在這種情況下信息只能被傳遞如果接受者類型和目標參數類型匹配,message可以是任何簡單或者復雜的對象,你可以用特定的消息類型或者創建你自己的類型繼承自他們。
Messenger首先需要注冊一下,用來接收消息
Messenger.Default.Register<string>(this, (o) =>
{
MessageBox.Show("收到字符串數據:" + o);
});
Messenger.Default.Register<string>(this, (o) =>
{
MessageBox.Show("收到字符串數據:" + o);
},"token");//帶令牌的注冊
// 接口注冊receiveDerivedMessagesToo為false,繼承的對象發送將不能接收,為TRUE繼承的對象發送可以接收
Messenger.Default.Register<IA>(this, false, (o) =>
{
});
比如Messanger.Default.Send<A>()//false,發送不能接收
Messanger.Default.Register<T>泛型方法,T代表指定類型,只有發送這個類型的消息才能被指定泛型注冊的方法捕獲到
消息發送:
Messenger.Default.Send("123");
Messenger.Default.Send("123", "token");//"token"消息令牌,如果帶了令牌,只有注冊了該令牌的消息才能接收到
Messenger.Default.Send<NotificationMessage>(new NotificationMessage(this, "123"));
Messenger.Default.Send(null, "token");//如果需要發送廣播消息,消息內容為空
Message消息對象類型 說明
MessageBase 簡單的消息類,攜帶可選的信息關於消息發布者的
GenericMessage<T> 泛型消息
NotificationMessage 用於發送一個string類型通知給接受者
NotificationMessage<T>
和上面一樣是一個,且具有泛型功能
NotificationMessage 向接受者發送一個通知,允許接受者向發送者回傳消息
NotificationMessageAction<T> NotificationMessage的泛型方式
DialogMessage 發送者(通常是View)顯示對話,並且傳遞調用者得回傳結果(用於回調),接受者可以選擇怎樣顯示對話框,可以使是標准的MessageBox也可也是自定義彈出窗口
PropertyChangedMessage<T> 用於廣播一個屬性的改變在發送者里,和PropertyChanged事件有完全箱體內各的目的,但是是一種弱聯系方式
DialogMessage發送代碼:
//通過命令發送令牌信息
public ICommand TestMathCommand
{
get
{
return new RelayCommand(() =>
{
DialogMessage msg = new DialogMessage("提示正文", MessageBoxCallBack);
//設置彈出的MessageBox的類型,包含兩個按鈕,一個"確認", 一個"取消"
msg.Button = MessageBoxButton.OKCancel;
msg.Caption = "標題";
Messenger.Default.Send<DialogMessage>(msg);
});
}
}
private void MessageBoxCallBack(MessageBoxResult ret)
{
if (ret == MessageBoxResult.OK)
{
MessageBox.Show("彈窗點擊了確認。繼續執行。");
}
}
DialogMessage接收代碼:
public MainWindow()
{
InitializeComponent();
Messenger.Default.Register<DialogMessage>(this, dlgmsg =>
{
var res = MessageBox.Show(dlgmsg.Content, dlgmsg.Caption, dlgmsg.Button);
dlgmsg.Callback(res); //這句會此起ViewModel中的MessageBoxCallBack調用
});
}
DialogMessage包含了彈出框需要的全部信息,包括標題,正文和回調函數。在這個Demo中需要注意一下MessageBox是模態的,因此當執行到MessageBox.Show()時,執行流會卡住,等到用戶點擊"OK"惑"Cancel"按鈕后,程序才會繼續執行。
NotificationMessageAction發送代碼:
//通過命令發送令牌信息
public ICommand TestMathCommand
{
get
{
return new RelayCommand(() =>
{
NotificationMessageAction<MessageBoxResult> msg = new NotificationMessageAction<MessageBoxResult>("主頁面測試", (ret) =>
{
if (ret == MessageBoxResult.OK)
{
MessageBox.Show("彈窗點擊了確認。繼續執行。");
}
}
);
Messenger.Default.Send<NotificationMessageAction<MessageBoxResult>>(msg);
});
}
}
NotificationMessageAction接收代碼:
public MainWindow()
{
InitializeComponent();
Messenger.Default.Register<NotificationMessageAction<MessageBoxResult>>(this, (msg) =>
{
var ret = MessageBox.Show("內容", "標題", MessageBoxButton.OKCancel);
//msg.Notification內容是“主頁面測試”
if (msg.Notification != null)
{
msg.Execute(ret);
}
}
);
}
如果ViewModel需要向View發送一個對象,可以使用 NotificationMessage<類型>的泛型版本
// PropertyChangedMessage屬性消息,當屬性更改會觸發消息通知,屬性需要把廣播的參數設置為true
比如:public string name
{
get
{
return _name;
}
set
{
set(ref _name,value,broadcast:true);
}
}
Messenger.Default.Register<PropertyChangedMessage<string>>(this, (o) =>
{
if (o.PropertyName == "MyProperty")// 區別一下哪個屬性進行了變化
{
}
});
六、MVVMLight DispatchHelper UI更新
在應用程序中,線程可以被看做是應用程序的一個較小的執行單位。每個應用程序都至少擁有一個線程,我們稱為主線程。當調用和操作主線程的時候,該操作將動作添加到一個隊列中,每個操作均按照將它們添加到隊列中的順序連續執行,但是可以通過為這些動作指定優先級來影響執行順序,而負責管理此隊列的對象稱之為線程調度程序。
我們知道,WPF程序中,控件是屬於UI線程的,如果試圖在子線程中訪問或者更新UI,就需要在子線程中通知主線程來處理UI, 通過向主線程的Dispatcher隊列注冊工作項,來通知UI線程更新結果。
Dispatcher提供兩個注冊工作項的方法:Invoke 和 BeginInvoke。
這兩個方法均調度一個委托來執行。Invoke 是同步調用,也就是說,直到 UI 線程實際執行完該委托它才返回。BeginInvoke是異步的,將立即返回。
代碼片段如下:
this.Dispatcher.BeginInvoke((Action)delegate() { 更新UI控件ing;
});
通常情況下,ViewModel 不從 DispatcherObject 繼承,不能訪問 Dispatcher 屬性。這時候,我們需要使用DispatcherHelper 組件來更新UI。
實際上,該類所做的是將主線程的調度程序保存在靜態屬性中,並公開一些實用的方法,以便通過統一的方式訪問。
為了實現正常功能,需要在主線程上初始化該類。
通常,在 MVVM Light 應用程序中,DispatcherHelper 可以在 App.xaml.cs 或者ViewModel的構造函數中進行初始化,App.xaml.cs 是定義應用程序啟動類的文件。
在 WPF 中,該類一般是在 App 構造函數中進行初始化的。
DispatcherHelper組件初始化以后,DispatcherHelper 類的 UIDispatcher 屬性包含對主線程的調度程序的引用。
但是一般很少直接使用該屬性,雖然確實可以使用。通常我們會使用 CheckBeginInvokeOnUi 方法來更新UI。
七、MVVMLight 消息對話框
首先實現IDialgService類,然后注冊類,然后調用類顯示消息對話框
注冊對話框類:
public class B : IA, IDialogService { public B() { } public void Show() { throw new NotImplementedException(); } public Task ShowError(string message, string title, string buttonText, Action afterHideCallback) { throw new NotImplementedException(); } public Task ShowError(Exception error, string title, string buttonText, Action afterHideCallback) { throw new NotImplementedException(); } public Task ShowMessage(string message, string title) { MessageBox.Show(message, title); return null; } public Task ShowMessage(string message, string title, string buttonText, Action afterHideCallback) { throw new NotImplementedException(); } public Task<bool> ShowMessage(string message, string title, string buttonConfirmText, string buttonCancelText, Action<bool> afterHideCallback) { throw new NotImplementedException(); } public Task ShowMessageBox(string message, string title) { throw new NotImplementedException(); } }
注冊類
// IDialogService的使用
SimpleIoc.Default.GetInstance<IDialogService>().ShowMessage("", "");