还是从头开始来。
1、区域上下文。
1.1、通过NuGet添加Prism.DryIoc。如下图。
1.2、新建WPF项目WpfApp1,创建Views和ViewModels文件夹,将MainWindow.xaml文件移动到
Views文件下,在ViewModels文件夹下添加MainWindowViewModel.cs文件。
1.2.1、MainWindow.xaml代码如下。
<Window x:Class="WpfApp1.Views.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:WpfApp1"xmlns:prism="http://prismlibrary.com/"mc:Ignorable="d"Title="MainWindow" Height="450" Width="800"><Grid><ContentControl prism:RegionManager.RegionName="ContentRegion" /></Grid>
</Window>
1.2.2、 MainWindowViewModel.cs代码如下。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace WpfApp1.ViewModels
{public class MainWindowViewModel:BindableBase{private string _title="属性绑定";public string Title{get { return _title; }set { SetProperty(ref _title, value); }}}
}
1.3、修改App.xaml代码如下。
<prism:PrismApplication x:Class="WpfApp1.App"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:local="clr-namespace:WpfApp1"xmlns:prism="http://prismlibrary.com/"><Application.Resources></Application.Resources>
</prism:PrismApplication>
1.4、 修改App.xaml.cs代码如下。
using System.Configuration;
using System.Data;
using System.Windows;
using WpfApp1.ViewModels;
using WpfApp1.Views;namespace WpfApp1
{/// <summary>/// Interaction logic for App.xaml/// </summary>public partial class App : PrismApplication{protected override void RegisterTypes(IContainerRegistry containerRegistry){}protected override Window CreateShell(){return Container.Resolve<MainWindow>();}protected override void ConfigureViewModelLocator(){base.ConfigureViewModelLocator();ViewModelLocationProvider.Register<MainWindow,MainWindowViewModel>();}protected override IModuleCatalog CreateModuleCatalog(){//表示WpfApp1.exe程序所在目录下的Modules文件return new DirectoryModuleCatalog() { ModulePath = @".\Modules" };}}}
1.5、新建WPF类库项目 WpfModule,新建文件夹Business添加Person.cs类,Person.cs代码如下。同样通过NuGet添加Prism.DryIoc。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;namespace WpfModule.Business
{public class Person : INotifyPropertyChanged{#region INotifyPropertyChangedpublic event PropertyChangedEventHandler PropertyChanged;protected void OnPropertyChanged([CallerMemberName] string propertyname = null){PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyname));}#endregion //INotifyPropertyChangedprivate string _firstName;public string FirstName{get { return _firstName; }set{_firstName = value;OnPropertyChanged();}}private string _lastName;public string LastName{get { return _lastName; }set{_lastName = value;OnPropertyChanged();}} private int _age;public int Age{ get { return _age; }set{_age = value;OnPropertyChanged();}}private DateTime? _lastUpdated;public DateTime? LastUpdated{get { return _lastUpdated; }set{_lastUpdated = value;OnPropertyChanged();}}public override string ToString(){return $"{FirstName} {LastName} is {Age} years old";}}
}
1.6、新建文件夹ViewModels,添加类PersonDetailViewModel.cs和PersonListViewModel.cs,PersonDetailViewModel.cs代码如下。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WpfModule.Business;namespace WpfModule.ViewModels
{public class PersonDetailViewModel : BindableBase{private Person _selectedPerson;public Person SelectedPerson{get { return _selectedPerson; }set { SetProperty(ref _selectedPerson, value); }}public PersonDetailViewModel(){}}
}
PersonListViewModel.cs代码如下。
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WpfModule.Business;namespace WpfModule.ViewModels
{public class PersonListViewModel:BindableBase{private ObservableCollection<Person> _people;public ObservableCollection<Person> People{get { return _people; }set { SetProperty(ref _people, value); }}public PersonListViewModel(){CreatePeople();}private void CreatePeople(){var people = new ObservableCollection<Person>();for (int i = 0; i < 10; i++){people.Add(new Person(){FirstName = String.Format("First {0}", i),LastName = String.Format("Last {0}", i),Age = i});}People = people;}}
}
1.7、新建文件夹Views,添加用户控件PersonDetail.xaml和PersonList.xaml。
PersonDetail.xaml代码如下。
<UserControl x:Class="WpfModule.Views.PersonDetail"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:WpfModule.Views"xmlns:prism="http://prismlibrary.com/" prism:ViewModelLocator.AutoWireViewModel="True" ><Grid x:Name="LayoutRoot" Background="White"><Grid.ColumnDefinitions><ColumnDefinition Width="Auto"/><ColumnDefinition /></Grid.ColumnDefinitions><Grid.RowDefinitions><RowDefinition Height="Auto"/><RowDefinition Height="Auto"/><RowDefinition Height="Auto"/></Grid.RowDefinitions><!-- First Name --><TextBlock Text="First Name:" Margin="5" /><TextBlock Grid.Column="1" Margin="5" Text="{Binding SelectedPerson.FirstName}" /><!-- Last Name --><TextBlock Grid.Row="1" Text="Last Name:" Margin="5" /><TextBlock Grid.Row="1" Grid.Column="1" Margin="5" Text="{Binding SelectedPerson.LastName}" /><!-- Age --><TextBlock Grid.Row="2" Text="Age:" Margin="5"/><TextBlock Grid.Row="2" Grid.Column="1" Margin="5" Text="{Binding SelectedPerson.Age}"/></Grid>
</UserControl>
PersonDetail.xaml.cs代码如下。
using Prism.Common;
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;
using WpfModule.Business;
using WpfModule.ViewModels;namespace WpfModule.Views
{/// <summary>/// PersonDetail.xaml 的交互逻辑/// </summary>public partial class PersonDetail : UserControl{public PersonDetail(){InitializeComponent();RegionContext.GetObservableContext(this).PropertyChanged += PersonDetail_PropertyChanged;}private void PersonDetail_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e){var context = (ObservableObject<object>)sender;var selectedPerson = (Person)context.Value;(DataContext as PersonDetailViewModel).SelectedPerson = selectedPerson;}}
}
PersonList.xaml代码如下。
<UserControl x:Class="WpfModule.Views.PersonList"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:WpfModule.Views"xmlns:prism="http://prismlibrary.com/"prism:ViewModelLocator.AutoWireViewModel="True" ><Grid x:Name="LayoutRoot" Background="White" Margin="10"><Grid.RowDefinitions><RowDefinition Height="100"/><RowDefinition Height="Auto"/></Grid.RowDefinitions><ListBox x:Name="_listOfPeople" ItemsSource="{Binding People}"/><ContentControl Grid.Row="1" Margin="10"prism:RegionManager.RegionName="PersonDetailsRegion"prism:RegionManager.RegionContext="{Binding SelectedItem, ElementName=_listOfPeople}"/></Grid>
</UserControl>
PersonList.xaml.cs代码如下。
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 WpfModule.Views
{/// <summary>/// PersonList.xaml 的交互逻辑/// </summary>public partial class PersonList : UserControl{public PersonList(){InitializeComponent();}}
}
1.8、新添加类WpfModuleA.cs,代码如下。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WpfModule.Views;namespace WpfModule
{public class WpfModuleA : IModule{public void OnInitialized(IContainerProvider containerProvider){var regionManager = containerProvider.Resolve<IRegionManager>();regionManager.RegisterViewWithRegion("ContentRegion", typeof(PersonList));regionManager.RegisterViewWithRegion("PersonDetailsRegion", typeof(PersonDetail));}public void RegisterTypes(IContainerRegistry containerRegistry){}}
}
1.9、个人理解,
regionManager.RegisterViewWithRegion("ContentRegion", typeof(PersonList));
将PersonList.xaml这个界面注册到MainWindow.xaml中的ContentRegion区域。
regionManager.RegisterViewWithRegion("PersonDetailsRegion", typeof(PersonDetail));
将PersonDetail.xaml这个界面注册到PersonList.xaml界面中的PersonDetailsRegion区域。
<ListBox x:Name="_listOfPeople" ItemsSource="{Binding People}"/>
将ListBox的数据源与People绑定。
<ContentControl Grid.Row="1" Margin="10"prism:RegionManager.RegionName="PersonDetailsRegion"prism:RegionManager.RegionContext="{Binding SelectedItem, ElementName=_listOfPeople}"/>
区域PersonDetailsRegion已与PersonDetail.xaml界面绑定,区域的上下文也就是prism:RegionManager.RegionContext,与控件listOfPeople(ListBox)的SelectedItem进行绑定。
在PersonDetail.xaml.cs中绑定了区域上下午属性变更方法,如下。
RegionContext.GetObservableContext(this).PropertyChanged += PersonDetail_PropertyChanged;
属性变更后执行的函数如下。
private void PersonDetail_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e){var context = (ObservableObject<object>)sender;var selectedPerson = (Person)context.Value;(DataContext as PersonDetailViewModel).SelectedPerson = selectedPerson;}