WPF笔记

MVVM模型

在实际的开发过程中,使用MVVM模型能够降低各组件之间的耦合度,增加单元可测试性。具体来说就是Model-View-ViewModel,其中View就是WPF默认给出的UI这个模块,Model是在后台负责执行具体的业务逻辑,和数据库进行沟通的模块,而ViewModel就是将二者串起来的桥梁,负责将业务逻辑和UI绑定。

View可以仅靠xaml和少量的C#构建,把DataContext设置为ViewModel即可,View基本上是不存在状态的,只是对ViewModel的绑定数据的显示。

ViewModel提供一些基本的字段供View绑定,同时封装了Model的部分底层逻辑接口,供View使用,ViewModel是存在状态的,因此提供了变量和属性来存储状态值。

Model是负责与数据库或者系统进行交流的底层模块,是程序业务实际执行的模块,能根据ViewModel给出的指令组合来依次完成任务。

ICommand

为了让UI能够执行逻辑,WPF控件利用ICommand接口来绑定操作。ICommand接口需要实现以下三个方法:

bool CanExecute(object parameter);
void Execute(object parameter);
event EventHandler CanExecuteChanged;

ICommand指出了绑定之后的控件能够做什么,什么时候能触发,什么时候可触发性改变。而ViewModel只需要提供一个公开的ICommand get接口,就可以在控件的Command属性中绑定。比如说Button和点击和Textbox的按键输入:

<TextBox>
    <TextBox.InputBindings>
        <KeyBinding Key="Enter" Command="{Binding XXXXCommand}" />
    </TextBox.InputBindings>
</TextBox>
<Button Command="{Binding XXXXCommand}"/>

Style

Style标签用于定义可重复使用的样式块。

如果是需要重用的Style,使用x:Key属性命名定义的Style,在之后就可以以Style="{StaticResource XXXX}“方式应用这个Style。

如果是仅仅用到一次,可以在<控件.Style>标签中定义Style标签,比如:

<Border>
    <Border.Style>
        <Style TargetType="Border">
            <Setter Property="Visibility" Value="Visible" />
        </Style>
    </Border.Style>
</Border>

Style标签中最常见的就是Setter标签,用于将某个属性设置为指定值。如果想要让Style支持在不同的条件下给出不同的值,可以用<Style.Triggers>来定义行为:

<Style.Triggers>
    <Trigger Property="IsMouseOver" Value="True">
        <Setter Property="Background" Value="#33FFFFFF"/>
    </Trigger>
    <DataTrigger Binding="{Binding ErrorText}" Value="{x:Null}">
        <Setter Property="Visibility" Value="Collapsed" />
    </DataTrigger>
</Style.Triggers>

Style中有一个非常特殊的属性Template,它允许你在保留这个控件根类型的情况下重新控制它的子控件的绘制。比如下面的代码,这里面又有一个特殊的ContextPresenter,它是用于将Button的Content属性放到此处。这里的Content是一个广义的概念,可以是字符串,也可以是另一个组件。

<Setter Property="Template">
    <Setter.Value>
        <ControlTemplate TargetType="Button">
            <Border Background="{TemplateBinding Background}">
                <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
            </Border>
        </ControlTemplate>
    </Setter.Value>
</Setter>