官网:https://primslibrary.com
源码地址:https://guthub.com/PrismLibrary/prism
Prism是由微软发布、维护的开源框架,提供了一组设计模式的实现,有助于编写结构良好的且可维护的XAML应用程序,包括MVVM、依赖注入、命令、事件聚合器等。
关键程序集
Prism.Core:实现MVVM的核心功能,是一个与平台无关的项目,可以在多个开发平台中使用(Prism.dll)。
- 如果只需要实现MVVM中的一些简单功能、例如属性变化通知、命令等,只需要在Nuget中安装
Prism.Core库即可。
Prism.Wpf:包含了DialogService、Region、Module、Navigation和其他一些WPF功能,使得WPF开发更加方便快捷(Prism.Wpf.dll)。
-
如果需要进一步使用WPF中的一些其他功能,可以在Nuget中安装
Prism.Wpf库,由于Prism.Wpf依赖于Prism.Core因此,无需再安装Prism.Core。
Prism.Unity:包含Prism.Unity.Wpf.dll、Prism.DryIoc.Wpf.dll。
-
如果需要使用IOC,则需要安装
Prism.Unity,由于Prism.Unity依赖于Prism.Wpf,因此不需要再安装Prism.Wpf和Prism.Core
数据处理
一、属性变化通知
Prism框架提供了BindableBase类,用于做数据处理(例如属性的变化通知等)。
五种属性变化通知方式
通过继承BindableBase类,可以更加便捷地在WPF中实现属性变化通知,具体有如下五种方式。
其中前三种没啥特殊的,第四种方式可以在属性变化时,通知其他属性的绑定控件;而第五种方式则可以在属性发生变化后调用指定的函数。
public class MainViewModel : BindableBase
{private string _value;public string Value{get { return _value; }set {// 第一种方式SetProperty(ref _value, value);// 第二种方式//this.OnPropertyChanged(new System.ComponentModel.PropertyChangedEventArgs("Value"));// 第三种方式//this.RaisePropertyChanged();// 第四种方式:可以通知另一个属性//SetProperty(ref _value, value, "Var");// 第五种方式//SetProperty(ref _value, value, OnValueChanged);}}private void OnValueChanged(){//属性成功变化后的执行函数}
}
二、数据异常处理
Prism框架提供了ErrorsContainer<T>类型专门用于处理项目中出现地异常。其中泛型T为指定的异常消息类型。
1、INotifyDataErrorInfo接口
使用ErrorsContainer<T>需要实现INotifyDataErrorInfo接口。
实现INotifyDataErrorInfo接口主要需要实现其中的三个成员,分别如下:
event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged:事件属性成员,用于异常通知。
bool HasErrors:属性成员,用于判断是否存在异常。
- 一般会通过
ErrorsContainer对象的HasErrors属性来进行判断。
IEnumerable GetErrors(string propertyName):方法成员,用于获取相关属性名称的异常。
- 一般会通过
ErrorsContainer对象的GetErrors方法来获得对应属性的异常。
public class MainViewModel :INotifyDataErrorInfo
{//声明ErrorsContainer对象,这里没有定义,详细做法请看下文public ErrorsContainer<string> _errorsContainer;public bool HasErrors => _errorsContainer.HasErrors;public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;public IEnumerable GetErrors(string propertyName){return _errorsContainer.GetErrors(propertyName);}......
}
2、ErrorsContainer类
构造函数
ErrorsContainer<T>(Action<string> raiseErrorsChanged):创建ErrorsContainer对象。
- raiseErrorsChanged:发生异常时的执行函数,函数中要去触发异常发生事件,也就是
INotifyDataErrorInfo接口的ErrorsChanged事件成员。
常用成员
bool HasErrors:属性成员,用于判断当前是否存在异常。
IEnumerable<T> GetErrors(string propertyName):获取指定属性的异常集合。
- propertyName:要获取异常的属性名称。
SetErrors(string propertyName, IEnumerable<T> newValidationResults):设置异常(也就是发生异常了)。
- propertyName:触发异常的属性名称。
- newValidationResults:异常集合,可以是
string数组,也可以是其他类型数组。
3、具体实现过程
异常处理编写
实现INotifyDataErrorInfo接口
public class MainViewModel : INotifyDataErrorInfo
{public bool HasErrors => throw new NotImplementedException();public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;public IEnumerable GetErrors(string propertyName){throw new NotImplementedException();}
}
定义ErrorsContainer<T>对象属性,完善INotifyDataErrorInfo成员实现
public class MainViewModel : INotifyDataErrorInfo
{//定义异常属性private ErrorsContainer<string> _errorsContainer;public ErrorsContainer<string> ErrorsContainer{get {if (_errorsContainer == null){_errorsContainer = new ErrorsContainer<string>(OnErrorHappend);}return _errorsContainer; }}//当异常发生时,触发异常发生事件private void OnErrorHappend(string obj){ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(obj));}public bool HasErrors => ErrorsContainer.HasErrors;public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;public IEnumerable GetErrors(string propertyName){return ErrorsContainer.GetErrors(propertyName);}
}
继承BindableBase类,定义属性并实现属性变化通知,在特定条件下发生异常
public class MainViewModel : BindableBase,INotifyDataErrorInfo
{......//上文的内容private int _value;public int Value{get { return _value; }set {if (value > 10){ErrorsContainer.SetErrors("Value", new string[] { "数值不能大于10" });}SetProperty(ref _value, value); }}
}
异常消息展示
在xaml中进行异常消息的使用
<Window ......><Window.DataContext><local:MainViewModel/></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 Value}"/><TextBox Text="{Binding Value,UpdateSourceTrigger=PropertyChanged}" Template="{StaticResource ct}"/></StackPanel></Grid>
</Window>