WPF 視覺狀態VisualState使用

ggtc發表於2024-06-23

VisualState基本使用

首先搭建一個自定義控制元件,繼承自ContentControl,自動生成了這些檔案
image
由於CustomButtonCustom名稱空間中,所以改一下xaml中的引用

xmlns:local="clr-namespace:WpfApp1.Custom"
  • 定義部件和視覺狀態
    TemplatePart是模板中的部件名
    TemplateVisualState是模板中的樣式名
[TemplatePart(Name = "P_Border")]
[TemplateVisualState(Name = mouseoverstate, GroupName = mousegroup)]
[TemplateVisualState(Name = mouseleavestate, GroupName = mousegroup)]
public class CustomButton : ContentControl
{
    public const string mouseoverstate = "mouseover";
    public const string mouseleavestate = "mouseleave";
    public const string mousegroup = "mousegroup1";
}
  • 新增樣式
    推薦把視覺狀態放在模板的根元素下,這個例子中是Border
<Style TargetType="{x:Type local:CustomButton}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:CustomButton}">
                <Border
                        x:Name="P_Border"
                        Padding="5"
                        CornerRadius="5"
                        Background="Transparent"
                        BorderBrush="Transparent"
                        BorderThickness="0">
                    <TextBlock Text="{TemplateBinding Content}" Foreground="White" HorizontalAlignment="Center"/>
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="mousegroup1">
                            <!--GoToState第三個引數useTransitions為false時進入這裡-->
                            <VisualState x:Name="mouseover">
                                <Storyboard>
                                    <ColorAnimation Storyboard.TargetName="P_Border" Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)" Duration="0:0:0" To="#FF16b777"/>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="mouseleave">
                                <Storyboard>
                                    <ColorAnimation Storyboard.TargetName="P_Border" Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)" Duration="0:0:0" To="#CC16b777"/>
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
  • 後臺程式碼
    這裡在滑鼠事件中改變視覺狀態
public override void OnApplyTemplate()
{
    base.OnApplyTemplate();
    VisualStateManager.GoToState(this, mouseleavestate, false);
}

protected override void OnMouseEnter(MouseEventArgs e)
{
    base.OnMouseEnter(e);
    VisualStateManager.GoToState(this, mouseoverstate, false);
}

protected override void OnMouseLeave(MouseEventArgs e)
{
    base.OnMouseLeave(e);
    VisualStateManager.GoToState(this, mouseleavestate, false);
}
  • 效果
    image

增加VisualTransition過渡效果

但這沒有過渡,新增過渡需要設定GoToState(this, mouseoverstate, true)
同時還要新增過渡效果的xaml元素

<VisualStateGroup x:Name="mousegroup1">
    <!--GoToState第三個引數useTransitions為true時進入這裡-->
    <VisualStateGroup.Transitions>
        <!--from是前一個狀態名,to是後一個狀態名-->
        <VisualTransition To="mouseover">
            <Storyboard>
                <!--(Border.Background).(SolidColorBrush.Color)是PropertyPath型別限定的單個屬性語法,格式為(targetTtype.property)-->
                <ColorAnimation Storyboard.TargetName="P_Border" Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)" Duration="0:0:1" To="#FF167777"/>
            </Storyboard>
        </VisualTransition>
        <VisualTransition To="mouseleave">
            <Storyboard>
                <ColorAnimation Storyboard.TargetName="P_Border" Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)" Duration="0:0:1" To="#AA167777"/>
            </Storyboard>
        </VisualTransition>
    </VisualStateGroup.Transitions>
    <!--GoToState第三個引數useTransitions為false時進入這裡-->
    <VisualState x:Name="mouseover">
        <Storyboard>
            <ColorAnimation Storyboard.TargetName="P_Border" Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)" Duration="0:0:0" To="#FF167777"/>
        </Storyboard>
    </VisualState>
    <VisualState x:Name="mouseleave">
        <Storyboard>
            <ColorAnimation Storyboard.TargetName="P_Border" Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)" Duration="0:0:0" To="#AA167777"/>
        </Storyboard>
    </VisualState>
</VisualStateGroup>

再把GoToState(this, mouseoverstate, false)改為true
但注意OnApplyTemplate中不要改,因為那裡是首次載入,許需要過渡

  • 效果
    image

相關文章