官网: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>