一.Prism介紹
二.程式啟動
1.方式1 8.0版本之前的方案
首先建立,Views和ViewModels資料夾,然後分別建立一個ViewModel類,以及一個View介面。
public class InfoViewModel { public InfoViewModel() { myVar = 333; } private int myVar; public int MyProperty { get { return myVar; } set { myVar = value; } } } public partial class InfoView : Window { public InfoView() { InitializeComponent(); this.DataContext = new InfoViewModel(); } } <TextBlock Text="{Binding MyProperty}" FontSize="25"></TextBlock>
然後,編寫一個BootStraper類,繼承自Prism.Unity下面的PrismBootstrapper類。複寫對應的方法。
public class BootStraper : PrismBootstrapper { protected override DependencyObject CreateShell() { return Container.Resolve<InfoView>(); } protected override void RegisterTypes(IContainerRegistry containerRegistry) { } }
最後,在App.xaml.cs中,複寫onstartup方法。
public partial class App : Application { protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); var bs = new BootStraper(); bs.Run(); } }
啟動程式就可以實現資料的繫結。
方式二,8.0版本提供的方式
需要修改App.xaml和App.xaml.cs裡面的程式碼。
public partial class App : PrismApplication { //protected override void OnStartup(StartupEventArgs e) //{ // base.OnStartup(e); // var bs = new BootStraper(); // bs.Run(); //} protected override Window CreateShell() { return Container.Resolve<InfoView>(); } protected override void RegisterTypes(IContainerRegistry containerRegistry) { } }
app.xaml.cs中的程式碼,需要繼承自PrismApplication,複寫其中的兩個方法。
在app.xaml中也需要更改。
<prism:PrismApplication xmlns:prism="http://prismlibrary.com/" x:Class="Prism_01.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:Prism_01" > <Application.Resources> </Application.Resources> </prism:PrismApplication>
自動注入資料,可以直接將datacontext資料刪除掉。這種是根據命名規則來進行自動注入的。*View與*ViewModel進行自動匹配,自動繫結。條件是資料夾名稱為Views和ViewModels。
三.資料繫結
1.自定義對應規則
也可以自定資料夾和檔案的命名規則,實現自動注入資料。在App.xaml.cs下面建立對應關係。,輸入的是view的型別,返回的是viewmodel的型別。
protected override void ConfigureViewModelLocator() { base.ConfigureViewModelLocator(); //設定統一的對應規則 ViewModelLocationProvider.SetDefaultViewTypeToViewModelTypeResolver((viewType)=> { //將view檔名替換為viewmodel檔名 var modelName= viewType.FullName.Replace("ANDONGLU.", "").Replace("View","ViewModel").Replace("AN",""); //將view的dll名替換為viewmodel的dll名稱。 var moduleName = viewType.Assembly.FullName; var t = $"{modelName },{moduleName}"; return Type.GetType(t); }); }
2.也可以建立一對一的對應關係
//一對一註冊,string->type ViewModelLocationProvider.Register(typeof(ANInfoView).ToString(), typeof(InfoViewModel)); //type->type ViewModelLocationProvider.Register<ANInfoView, InfoViewModel>(); //string=>func ViewModelLocationProvider.Register(typeof(ANInfoView).ToString(), () => { return Container.Resolve<InfoViewModel>(); });
3.在datacontext中引入物件
<Window.DataContext> <prism:ContainerProvider Type="{x:Type vm:InfoViewModel}"></prism:ContainerProvider> </Window.DataContext>
四.資料雙向繫結
public class InfoViewModel:BindableBase { public InfoViewModel() { myVar = 333; } private int myVar; public int MyProperty { get { return myVar; } set { myVar = value; //this.RaisePropertyChanged(); //設定屬性值 //this.SetProperty<int>(ref myVar,value); //設定屬性值的同時,提供回撥函式,當值變化值可以呼叫 //this.SetProperty<int>(ref myVar,value,()=> { //}); } } }
ViewModel類需要繼承自BindableBase型別,然後需要在屬性的set裡面設定值變化的通知。
Prism提供了多種通知方式。
五.資料驗證
資料的驗證可以在特性裡面進行驗證。在Prism.Unity裡面是透過屬性之中編寫驗證規則進行驗證。驗證結果需要放置到ErrorContainer裡面。透過繼承INotifyDataErrorInfo,處理Error資訊。所有的驗證程式碼都是在ViewModel裡面實現的。
public class InfoViewModel:BindableBase, INotifyDataErrorInfo { public InfoViewModel() { myVar = 333; } private int myVar; public int MyProperty { get { return myVar; } set { //myVar = value; //this.RaisePropertyChanged(); //this.SetProperty<int>(ref myVar,value); this.SetProperty<int>(ref myVar, value, () => { }); if (value == 1231 || value == 12322) { ErrorContainer.SetErrors("MyProperty", new string[] { "輸入值有誤!" }); } else { ErrorContainer.ClearErrors("MyProperty"); } } } private ErrorsContainer<string> errorContainer; public ErrorsContainer<string> ErrorContainer { get { if (errorContainer == null) { errorContainer = new ErrorsContainer<string>(propName=> { ErrorsChanged?.Invoke(this,new DataErrorsChangedEventArgs(propName)); }); } return errorContainer; } set { errorContainer = value; } } public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged; public bool HasErrors => ErrorContainer==null?false:ErrorContainer.HasErrors; public IEnumerable GetErrors(string propertyName) =>ErrorContainer==null?null:ErrorContainer.GetErrors(propertyName); }
介面程式,需要在介面上新增一個Error提示,需要建立一個模板樣式。
<Window x:Class="Prism_01.ANDONGLU.Views.ANInfoView" 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:Prism_01.ANDONGLU.Views" xmlns:vm="clr-namespace:Prism_01.ViewModels" xmlns:prism="http://prismlibrary.com/" mc:Ignorable="d" Title="AN" Height="450" Width="800"> <Window.DataContext> <prism:ContainerProvider Type="{x:Type vm:InfoViewModel}"></prism:ContainerProvider> </Window.DataContext> <Window.Resources> <ControlTemplate TargetType="{x:Type TextBox}" x:Key="ct"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="auto"/> <RowDefinition Height="auto"/> </Grid.RowDefinitions> <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True" CornerRadius="5"> <ScrollViewer x:Name="PART_ContentHost" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden" VerticalContentAlignment="Center" Margin="3,5" BorderThickness="0"/> </Border> <TextBlock Grid.Row="1" Text="{Binding (Validation.Errors)[0].ErrorContent,RelativeSource={RelativeSource AncestorType=TextBox,Mode=FindAncestor}}" Foreground="Red" Margin="10,5" Name="txtError"/> </Grid> <ControlTemplate.Triggers> <Trigger Property="Validation.HasError" Value="True"> <Setter Property="Visibility" Value="Visible" TargetName="txtError"/> <Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Window.Resources> <Grid> <StackPanel> <TextBlock Text="{Binding MyProperty}" FontSize="30"></TextBlock> <TextBox Text="{Binding MyProperty,UpdateSourceTrigger=PropertyChanged}" FontSize="30" Template="{StaticResource ct}"></TextBox> </StackPanel> </Grid> </Window>