wpf入门第四篇 VisualState

前言

本文是wpf入门系列第四篇,面向有winform或者web前端基础的、并且也有C#基础的同学。

在WPF中,View(Window,UserControl等)常常会根据不同的状态来显示不同的内容,比如消息的未读和已读是两种状态,这两种状态下View的表现形式会有所差别。本文将从头开始一个的示例项目,来简单的介绍VisualState的用法。

本文使用了 Visual Studio 2017 进行演示讲解。

wpf入门系列导航页面: https://blog.****.net/wf824284257/article/details/88757497

上一步: wpf入门第三篇 ControlTemplate、Trigger与Storyboard
https://blog.****.net/wf824284257/article/details/88783979

开始

打开 VS2017,新建WPF项目,命名为 WpfVisualStateTest ,点击确定。

wpf入门第四篇 VisualState

向项目中添加一个用户控件. 右键点击项目名,选择【添加】->【用户控件】,命名为Msg 。

wpf入门第四篇 VisualState

将Msg.xaml 代码替换为如下代码:

<UserControl x:Class="WpfVisualStateTest.Msg"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
            xmlns:local="clr-namespace:WpfVisualStateTest"
            mc:Ignorable="d" 
            d:DesignHeight="450" d:DesignWidth="800" Height="80">
    <Border Name="bdMain" CornerRadius="10"  Background="White" BorderBrush="#333" BorderThickness="1" Margin="10"
            MouseLeftButtonDown="Border_MouseLeftButtonDown" >
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="StateRead">
                <VisualState x:Name="HasRead">
                    <Storyboard>
                        <DoubleAnimation 
                            Storyboard.TargetName="bdMain" 
                            Storyboard.TargetProperty="Opacity" 
                            To="0.1" 
                            Duration="0:0:1"></DoubleAnimation>
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
        <Grid Name="gdMain" >
            <Grid.RowDefinitions>
                <RowDefinition Name="rowTitle"></RowDefinition>
                <RowDefinition Name="rowBody"></RowDefinition>
            </Grid.RowDefinitions>
            <TextBlock Grid.Row="0" Name="tTitle" VerticalAlignment="Center" Margin="10,0,0,0" 
                    FontSize="20" Foreground="Black" Text="{Binding Title}"></TextBlock>
            <TextBlock Grid.Row="1" Name="tBody" VerticalAlignment="Center" Margin="10,0,0,0" 
                    FontSize="15" Foreground="#888" Text="{Binding Body}"></TextBlock>
        </Grid>
    </Border>
</UserControl>

根据代码可以看出,我们在Msg用户控件中添加了两行,第一行是比较显眼的TItle,第二行是弱一点的Body. 两个TextBlock的Text属性都使用了Binding。 现在我们需要一个VierModel来驱动我们的View。

向项目中添加一个VM_Msg类,并将代码替换为下面代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WpfVisualStateTest
{
    public class VM_Msg
    {
        public string Title { get; set; }
        public string Body { get; set; }
    }
}

打开 Msg.xaml.cs ,使用下面的代码来替换原本内容。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfVisualStateTest
{
    /// <summary>
    /// Msg.xaml 的交互逻辑
    /// </summary>
    public partial class Msg : UserControl
    {
        public Msg(VM_Msg vm)
        {
            InitializeComponent();
            this.DataContext = vm;
        }
        private void Border_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            VisualStateManager.GoToState(this, "HasRead", false);
        }
    }
}

Border_MouseLeftButtonDown 中写了改变控件状态的代码。下面我们来试运行一下,看看是否可以达到我们的预期效果。

打开MainWindow.xaml,将代码替换为如下代码:

<Window x:Class="WpfVisualStateTest.MainWindow"
        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:WpfVisualStateTest"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <StackPanel Name="spList" Orientation="Vertical">
            
        </StackPanel>
    </Grid>
</Window>

打开MainWindow.xaml.cs ,将代码替换为如下代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfVisualStateTest
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            VM_Msg vm = new VM_Msg()
            {
                Title = "WPF的VisualState",
                Body = "在WPF中,View(Window,UserControl等)常常会根据不同的状态来显示不同的内容"
            };
            Msg msg = new Msg(vm);
            spList.Children.Add(msg);
        }
    }
}

F5 运行项目,点击Msg控件,可以看到它逐渐变得透明。

wpf入门第四篇 VisualState

我们新加一个State,使得Msg重新回到原来的状态,并为Msg的Border添加一个右键点击事件来进入这个状态。

将Msg.xaml的 Border及VisualStateManager 代码改为如下代码:

<Border Name="bdMain" CornerRadius="10"  Background="White" BorderBrush="#333" BorderThickness="1" Margin="10"
        MouseLeftButtonDown="Border_MouseLeftButtonDown" MouseRightButtonDown="BdMain_MouseRightButtonDown">
<VisualStateManager.VisualStateGroups>
    <VisualStateGroup x:Name="StateRead">
        <VisualState x:Name="HasRead">
            <Storyboard>
                <DoubleAnimation 
                    Storyboard.TargetName="bdMain" 
                    Storyboard.TargetProperty="Opacity" 
                    To="0.1" 
                    Duration="0:0:1"></DoubleAnimation>
            </Storyboard>
        </VisualState>
        <VisualState x:Name="NotRead">
            <Storyboard>
                <DoubleAnimation 
                    Storyboard.TargetName="bdMain" 
                    Storyboard.TargetProperty="Opacity" 
                    To="1" 
                    Duration="0:0:1"></DoubleAnimation>
            </Storyboard>
        </VisualState>
    </VisualStateGroup>
</VisualStateManager.VisualStateGroups>

在Msg.xaml.cs中添加右键点击事件

private void BdMain_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
    VisualStateManager.GoToState(this, "NotRead", false);
}

F5 运行项目,左键点击Msg控件后它将逐渐变得透明,之后右键点击Msg控件后它将逐渐恢复。

wpf入门第四篇 VisualState

结束

本文通过一个小的测试项目来简单说明了 WPF 中 VisualState 的用法。若有其他需要可留言,24小时内回复。

本文所用代码示例可以在博主的资源页下载: https://download.****.net/download/wf824284257/11084852

若有不足请指正,感谢。