背景说明
在项目开发过程过程中,常常会遇到单个窗体作为容器,但是需要多个界面之间的跳转问题,此时,则需要公用ViewModel,尤其是在跳转的子界面。
案例说明
当前案例是将需要跳转窗体的ViewModel作为全局的集合,在ViewModel内进行实例化,同时,在跳转的子窗体也是绑定这个静态的全局ViewModel,这样就可以将子窗体的委托事件作为公共化,可以提供在其他的窗体进行订阅,实现1号窗体的方法可以触发2号窗体的功能。
代码如下
MyCommand代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace GlobalMVVM
{
public class MyCommand:ICommand
{
private readonly Action _execute;
private readonly Func<bool> _canExecute;
private readonly Action<object> _execute2;
public MyCommand(Action execute, Func<bool> canExecute = null)
{
_execute = execute ?? throw new ArgumentNullException(nameof(execute));
_canExecute = canExecute;
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public bool CanExecute(object parameter)
{
return _canExecute == null || _canExecute();
}
public void Execute(object parameter)
{
_execute();
}
}
}
Notify
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace GlobalMVVM
{
public abstract class Notify : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string name = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
}
CTQHMainView.xaml
<Window x:Class="GlobalMVVM.View.CTQHMainView"
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:GlobalMVVM.View"
mc:Ignorable="d"
Title="CTQHMainView" Height="450" Width="800">
<Grid>
<ContentControl Margin="0,0,5,0" Background="Transparent" Content="{Binding CurrentViewModel}" BorderThickness="0"/>
</Grid>
</Window>
CTQHMainView.cs
using GlobalMVVM.ViewModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace GlobalMVVM.View
{
/// <summary>
/// CTQHMainView.xaml 的交互逻辑
/// </summary>
public partial class CTQHMainView : Window
{
public CTQHMainView()
{
InitializeComponent();
this.DataContext = new CTQHMainViewModel();
}
}
}
Page1View.xaml
<Page x:Class="GlobalMVVM.View.Page1View"
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:local="clr-namespace:GlobalMVVM.View"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
Title="Page1View">
<Grid>
<Button Content="进入界面2" HorizontalAlignment="Left" VerticalAlignment="Top" Command="{Binding CQTHCommand2}" Margin="365,236,0,0"/>
</Grid>
</Page>
Page1View.cs
using GlobalMVVM.ViewModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace GlobalMVVM.View
{
/// <summary>
/// Page1View.xaml 的交互逻辑
/// </summary>
public partial class Page1View : Page
{
public Page1View()
{
InitializeComponent();
this.DataContext = CTQHMainViewModel.page1Model1;
}
}
}
Page2View.xaml
<Page x:Class="GlobalMVVM.View.Page2View"
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:local="clr-namespace:GlobalMVVM.View"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
Title="Page2View">
<Grid>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Border Grid.Row="0" Background="Blue"/>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border Grid.Column="0" Background="Crimson"/>
<Border Grid.Column="1" Background="Red"/>
</Grid>
</Grid>
<Button Content="返回界面1" HorizontalAlignment="Left" VerticalAlignment="Top" Command="{Binding CQTHCommand1}" Margin="726,21,0,0"/>
</Grid>
</Page>
Page2View.cs
using GlobalMVVM.ViewModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace GlobalMVVM.View
{
/// <summary>
/// Page2View.xaml 的交互逻辑
/// </summary>
public partial class Page2View : Page
{
public Page2View()
{
InitializeComponent();
this.DataContext = CTQHMainViewModel.page1Model2;
}
}
}
CTQHMainViewModel
using GlobalMVVM.View;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
namespace GlobalMVVM.ViewModel
{
public class CTQHMainViewModel : Notify
{
public MyCommand CQTHCommand1 { set; get; }
public MyCommand CQTHCommand2 { set; get; }
private Page1View page1 = new Page1View();
private Page2View page2 = new Page2View();
public static Page1ViewModel page1Model1 = new Page1ViewModel();
public static Page2ViewModel page1Model2 = new Page2ViewModel();
public CTQHMainViewModel()
{
CQTHCommand1 = new MyCommand(ShowPage1);
ShowPage1();
page1Model1.MethodExecuted += MyUserControl_MyButtonClicked;
page1Model2.MethodExecuted += MyUserControl_MyButtonClicked2;
}
private Frame currenrframe;
public Frame CurrentViewModel
{
get { return currenrframe; }
set
{
currenrframe = value;
OnPropertyChanged();
}
}
public void ShowPage1()
{
Page frm = (Page)page1;
Frame frame = new Frame();
frame.Content = frm;
CurrentViewModel = frame;
}
private void MyUserControl_MyButtonClicked(object sender, System.EventArgs e)
{
Page frm = (Page)page2;
Frame frame = new Frame();
frame.Content = frm;
CurrentViewModel = frame;
}
private void MyUserControl_MyButtonClicked2(object sender, System.EventArgs e)
{
Page frm = (Page)page1;
Frame frame = new Frame();
frame.Content = frm;
CurrentViewModel = frame;
}
}
}
Page1ViewModel
using GlobalMVVM.View;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
namespace GlobalMVVM.ViewModel
{
public class Page1ViewModel : Notify
{
public event EventHandler MethodExecuted;
public static MyCommand CQTHCommand2 { set; get; }
private Page2View page2 = new Page2View();
public Page1ViewModel()
{
CQTHCommand2 = new MyCommand(ShowPage2);
}
private Frame currenrframe;
public Frame CurrentViewModel
{
get { return currenrframe; }
set
{
currenrframe = value;
OnPropertyChanged();
}
}
public void ShowPage2()
{
// 触发事件
MethodExecuted?.Invoke(this, EventArgs.Empty);
}
}
}
Page2ViewModel
using GlobalMVVM.View;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
namespace GlobalMVVM.ViewModel
{
public class Page2ViewModel : Notify
{
public event EventHandler MethodExecuted;
public static MyCommand CQTHCommand1 { set; get; }
private Page1View page2 = new Page1View();
public Page2ViewModel()
{
CQTHCommand1 = new MyCommand(ShowPage1);
}
private Frame currenrframe;
public Frame CurrentViewModel
{
get { return currenrframe; }
set
{
currenrframe = value;
OnPropertyChanged();
}
}
public void ShowPage1()
{
// 触发事件
MethodExecuted?.Invoke(this, EventArgs.Empty);
}
}
}