WPF入门到跪下 第十一章 Prism(一)数据处理

发布时间:2024年01月20日

官网:https://primslibrary.com
源码地址:https://guthub.com/PrismLibrary/prism
Prism是由微软发布、维护的开源框架,提供了一组设计模式的实现,有助于编写结构良好的且可维护的XAML应用程序,包括MVVM、依赖注入、命令、事件聚合器等。
关键程序集
Prism.Core:实现MVVM的核心功能,是一个与平台无关的项目,可以在多个开发平台中使用(Prism.dll)。

  • 如果只需要实现MVVM中的一些简单功能、例如属性变化通知、命令等,只需要在Nuget中安装Prism.Core库即可。在这里插入图片描述

Prism.Wpf:包含了DialogServiceRegionModuleNavigation和其他一些WPF功能,使得WPF开发更加方便快捷(Prism.Wpf.dll)。

  • 如果需要进一步使用WPF中的一些其他功能,可以在Nuget中安装Prism.Wpf库,由于Prism.Wpf依赖于Prism.Core因此,无需再安装Prism.Core

    在这里插入图片描述

Prism.Unity:包含Prism.Unity.Wpf.dllPrism.DryIoc.Wpf.dll

  • 如果需要使用IOC,则需要安装Prism.Unity,由于Prism.Unity依赖于Prism.Wpf,因此不需要再安装Prism.WpfPrism.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>
文章来源:https://blog.csdn.net/jjailsa/article/details/135708375
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。