• WPF(触发器)


    使用触发器,可以动态地更改控件的外观,因为一些事件或属性值改变了。通常这都必须在代码中实现,使用WPF,也可以用XAML实现,而这只会影响UI。

    1.属性触发器

    属性触发器在属性值改变时激活。Style类有一个Triggers属性,通过它可以指定属性触发器。

    <Window x:Class="WpfAppLearn1.Window4"
            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:WpfAppLearn1"
            mc:Ignorable="d" Title="Window4" Height="450" Width="800">
        <Canvas HorizontalAlignment="Left" Height="281" VerticalAlignment="Top" Width="679">
            <Canvas.Resources>
                <Style x:Key="tbStyle1" TargetType="TextBox">
                    <Setter Property="Background" Value="Aqua" />
                    <Setter Property="Foreground" Value="Chocolate" />
                    <Style.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="Background" Value="AliceBlue" />
                            <Setter Property="Text" Value="Hello" />
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </Canvas.Resources>
            <TextBox Style="{StaticResource tbStyle1}" Height="23" Width="120" Canvas.Left="175" Canvas.Top="107" />
        </Canvas>
    </Window>

    上述代码,当鼠标移入TextBox时,将背景色改为AliceBlue,文本改为Hello。当 鼠标移出TextBox时,样式会恢复本来的效果,这里就会将背景色重新设置为Aqua,文本变为空。

    PS:触发器触发时要修改的值若不是控件的默认值,就必须在样式中定义,否则触发没效果。

    <TextBox Style="{StaticResource tbStyle1}" Background="Beige" Height="23" Width="120" />

    若是直接给TextBox定义背景色,当触发器激活时,并不会改变控件的背景色,文本效果还是可以触发的,若是直接定义文本不为TextBox(TextBox的Text默认值为TextBox)时也不会达到效果。

    2.多触发器 

    属性的值变化时,就会激活属性触发器,如果因为两个或多个属性同时改变时激活触发器,就可以使用MultiTrigger。

    <Window x:Class="WpfAppLearn1.Window4"
            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:WpfAppLearn1"
            mc:Ignorable="d"
            Title="Window4" Height="450" Width="800">
        <Canvas HorizontalAlignment="Left" Height="281" VerticalAlignment="Top" Width="679">
            <Canvas.Resources>
                <Style x:Key="tbStyle1" TargetType="TextBox">
                    <Setter Property="Background" Value="Aqua" />
                    <Setter Property="Foreground" Value="Chocolate" />
                    <Style.Triggers>
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="Text" Value="123" />
                                <Condition Property="IsMouseOver" Value="True" />
                            </MultiTrigger.Conditions>
                            <MultiTrigger.Setters>
                                <Setter Property="Background" Value="Yellow" />
                                <Setter Property="Foreground" Value="Red" />
                            </MultiTrigger.Setters>
                        </MultiTrigger>
                    </Style.Triggers>
                </Style>
            </Canvas.Resources>
            <TextBox Style="{StaticResource tbStyle1}" Height="23" Width="120" Canvas.Left="175" Canvas.Top="107" />
        </Canvas>
    </Window>

    上述代码,当鼠标移入TextBox且Text为123时激活触发器。 


    触发器就相当于事件,也区分订阅的顺序,当激活时按住订阅的顺序依次触发。下述代码当鼠标移入且Text为123时的背景色并不是Yellow,而是AliceBlue。

    <Window x:Class="WpfAppLearn1.Window4"
            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:WpfAppLearn1"
            mc:Ignorable="d"
            Title="Window4" Height="450" Width="800">
        <Canvas HorizontalAlignment="Left" Height="281" VerticalAlignment="Top" Width="679">
            <Canvas.Resources>
                <Style x:Key="tbStyle1" TargetType="TextBox">
                    <Setter Property="Background" Value="Aqua" />
                    <Setter Property="Foreground" Value="Chocolate" />
                    <Style.Triggers>
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="Text" Value="123" />
                                <Condition Property="IsMouseOver" Value="True" />
                            </MultiTrigger.Conditions>
                            <MultiTrigger.Setters>
                                <Setter Property="Background" Value="Yellow" />
                                <Setter Property="Foreground" Value="Red" />
                            </MultiTrigger.Setters>
                        </MultiTrigger>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="Background" Value="AliceBlue" />
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </Canvas.Resources>
            <TextBox Style="{StaticResource tbStyle1}" Height="23" Width="120" Canvas.Left="175" Canvas.Top="107" />
        </Canvas>
    </Window>

     3.事件触发器

    除了使用属性触发器之外,还可以定义一个事件触发器,来启动动画。属性触发器在属性改变其值时激活,事件触发器在事件发生时激活。控件存在的事件都有对应的事件触发器。

    <Window x:Class="WpfAppLearn1.Window3" 
            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:WpfAppLearn1" 
            mc:Ignorable="d" Title="Window3" Height="206" Width="509" WindowStartupLocation="CenterScreen">
        <Canvas x:Name="canvas1" Background="#FFCFC9C9" Margin="0,0,1,0" Width="500">
            <TextBox x:Name="tb1" Height="23" TextWrapping="Wrap" Text="TextBox" Width="120" Canvas.Left="60" Canvas.Top="75">
                <TextBox.Style>
                    <Style TargetType="TextBox">
                        <Style.Triggers>
                            <EventTrigger RoutedEvent="MouseEnter">
                                <BeginStoryboard>
                                    <Storyboard FillBehavior="Stop">
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background">
                                            <DiscreteObjectKeyFrame KeyTime="0:0:0">
                                                <DiscreteObjectKeyFrame.Value>
                                                    <SolidColorBrush Color="OrangeRed" />
                                                </DiscreteObjectKeyFrame.Value>
                                            </DiscreteObjectKeyFrame>
                                        </ObjectAnimationUsingKeyFrames>
                                    </Storyboard>
                                </BeginStoryboard>
                            </EventTrigger>
                        </Style.Triggers>
                    </Style>
                </TextBox.Style>
            </TextBox>
        </Canvas>
    </Window>

    上例定义一个一个鼠标移入控件时的事件触发器。有没有考虑过,如果订阅了一个鼠标移入事件的话,那时触发器先执行还是事件先执行呢??? 

    private void tb1_MouseEnter(object sender, MouseEventArgs e)
    {
        this.tb1.Background = new SolidColorBrush(Colors.Blue);
    }

    结果表明,事件会是最后触发的,触发顺序:事件触发器 -> 属性触发器 -> 事件

    4.数据触发器 

    如果绑定到控件上的数据满足指定条件,就激活数据触发器。

    public class Book
    {
        public string Title { get; set; }
     
        public string Publisher { get; set; }
     
        public string Isbn { get; set; }
     
        public override string ToString()
        {
            return $"{Title},{Publisher},{Isbn}";
        }
    }
    <Window x:Class="WpfAppLearn2.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:WpfAppLearn2"
            mc:Ignorable="d"
            Title="MainWindow" Height="450" Width="319" Background="#FFD4D2D2" WindowStartupLocation="CenterScreen">
        <Window.Resources>
            <local:Book x:Key="theBook" Title="C#" Publisher="MS" Isbn="123456"/>
        </Window.Resources>
        <Canvas DataContext="{StaticResource theBook}" HorizontalAlignment="Left" VerticalAlignment="Top">
            <Canvas.Resources>
                <Style x:Key="tbStyle" TargetType="TextBox">
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding Path=Title}" Value="C#4.0">
                            <Setter Property="Foreground" Value="Red"/>
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </Canvas.Resources>
            <TextBox Height="23" Style="{StaticResource tbStyle}" Text="{Binding Title}" Width="120" Canvas.Left="65" Canvas.Top="235"/>
            <TextBox Height="23" Style="{StaticResource tbStyle}" Text="{Binding Title}" Width="120" Canvas.Left="65" Canvas.Top="195"/>
        </Canvas>
    </Window>

    其中两个TextBox控件的Text属性都是绑定了Title属性,所以当其中一个TextBox的Text属性值发生改变时也会影响另一个TextBox。而数据触发器是根据绑定的数据来判断是否激活,所以当其中一个Text改为C#4.0,并确定修改,更新到Title属性中后,两个TextBox的前景色都会改为Red。 

  • 相关阅读:
    怎样整理房间
    拙劣的外部变量
    鸡窝里飞出伪凤凰
    flag标志什么?哦,它标志代码馊了——(三)
    边界测试——让BUG现形
    static的滥用与变态的阉割
    无知乱吃药
    flag标志什么?哦,它标志代码馊了——(一)
    flag标志什么?哦,它标志代码馊了——(二)
    半身不遂和粗中有细
  • 原文地址:https://www.cnblogs.com/bridgew/p/16138036.html
Copyright © 2020-2023  润新知