Установка начального значения VisualState

Phil Jollans спросил: 14 ноября 2017 в 07:31 в: c#

У меня проблема с пользовательским элементом управления, использующим VisualStateManager.

Переходы между состояниями работают, как я ожидаю, но я не понимаю, как установить начальное состояние.

Я сделал полный пример, чтобы проиллюстрировать проблему. Этот пример использует пользовательский элемент управления, основанный на ButtonBase.

Элемент управления имеет группу VisualState с двумя состояниями "Проверено" и "Не проверено". Это код C # элемент управления.

using System.Windows;
using System.Windows.Controls.Primitives;namespace VisualStateTest
{
  [TemplateVisualStateAttribute(Name = "Checked",           GroupName = "CheckStates")]
  [TemplateVisualStateAttribute(Name = "Unchecked",         GroupName = "CheckStates")]
  public class CustomButton : ButtonBase
  {
    public static readonly DependencyProperty IsCheckedProperty =
        DependencyProperty.Register ( "IsChecked",
                                      typeof(bool),
                                      typeof(CustomButton),
                                      new FrameworkPropertyMetadata ( false,
                                                                      FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                                                                      OnCheckedChanged ) ) ;    static CustomButton()
    {
      DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomButton), new FrameworkPropertyMetadata(typeof(CustomButton)));
    }    public bool IsChecked
    {
      get { return (bool)GetValue(IsCheckedProperty); }
      set { SetValue(IsCheckedProperty, value); }
    }    public static void OnCheckedChanged ( DependencyObject d, DependencyPropertyChangedEventArgs e )
    {
      var button = d as CustomButton ;      if ((bool)e.NewValue)
      {
        VisualStateManager.GoToState(button, "Checked", true);
      }
      else
      {
        VisualStateManager.GoToState(button, "Unchecked", true);
      }
    }  }
}

Шаблон элемента управления показывает тень слева и сверху, когда установлено свойство IsChecked.

(я знаю, что дизайн плохо, но это не вопрос графического дизайна.)

Это шаблон элемента управления:

<ResourceDictionary
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:local="clr-namespace:VisualStateTest">  <Style TargetType="{x:Type local:CustomButton}">
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="{x:Type local:CustomButton}">          <Border x:Name="outerborder"
                  Background="{TemplateBinding Background}"
                  BorderBrush="{TemplateBinding BorderBrush}"
                  BorderThickness="{TemplateBinding BorderThickness}">            <VisualStateManager.VisualStateGroups>              <VisualStateGroup x:Name="CheckStates">                <VisualState x:Name="Checked">
                  <Storyboard>                    <DoubleAnimationUsingKeyFrames BeginTime="0:0:0"
                                              Storyboard.TargetName="topshadow"
                                              Storyboard.TargetProperty="(UIElement.Opacity)">
                      <SplineDoubleKeyFrame KeyTime="0:0:0.5" Value="1.0"/>
                    </DoubleAnimationUsingKeyFrames>                    <DoubleAnimationUsingKeyFrames BeginTime="0:0:0"
                                              Storyboard.TargetName="leftshadow"
                                              Storyboard.TargetProperty="(UIElement.Opacity)">
                      <SplineDoubleKeyFrame KeyTime="0:0:0.5" Value="1.0"/>
                    </DoubleAnimationUsingKeyFrames>                  </Storyboard>
                </VisualState>                <VisualState x:Name="Unchecked">
                  <Storyboard>                    <DoubleAnimationUsingKeyFrames BeginTime="0:0:0"
                                              Storyboard.TargetName="topshadow"
                                              Storyboard.TargetProperty="(UIElement.Opacity)">
                      <SplineDoubleKeyFrame KeyTime="0:0:0.5" Value="0"/>
                    </DoubleAnimationUsingKeyFrames>                    <DoubleAnimationUsingKeyFrames BeginTime="0:0:0"
                                              Storyboard.TargetName="leftshadow"
                                              Storyboard.TargetProperty="(UIElement.Opacity)">
                      <SplineDoubleKeyFrame KeyTime="0:0:0.5" Value="0"/>
                    </DoubleAnimationUsingKeyFrames>                  </Storyboard>
                </VisualState>              </VisualStateGroup>            </VisualStateManager.VisualStateGroups>            <Grid Cursor="Hand" ClipToBounds="True">              <Grid.RowDefinitions>
                <RowDefinition Height="10"/>
                <RowDefinition Height="*"/>
              </Grid.RowDefinitions>
              <Grid.ColumnDefinitions>
                <ColumnDefinition Width="10"/>
                <ColumnDefinition Width="*"/>
              </Grid.ColumnDefinitions>              <Rectangle x:Name="lineargradient"
                         Grid.RowSpan="2" Grid.ColumnSpan="2"
                         Stroke="#7F000000"
                         StrokeThickness="0">
                <Rectangle.Fill>
                  <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                    <GradientStop Color="#20808080"/>
                    <GradientStop Color="#008A8A8A" Offset="0.5"/>
                    <GradientStop Color="#20000000" Offset="1"/>
                  </LinearGradientBrush>
                </Rectangle.Fill>
              </Rectangle>              <ContentPresenter HorizontalAlignment="Center"
                                x:Name="contentPresenter"
                                Grid.RowSpan="2" Grid.ColumnSpan="2"
                                VerticalAlignment="Center" />              <Rectangle x:Name="topshadow"  Fill="#40000000" Grid.Row="0" Grid.ColumnSpan="2" Opacity="0">
                <Rectangle.Effect>
                  <BlurEffect Radius="3"/>
                </Rectangle.Effect>
              </Rectangle>
              <Rectangle x:Name="leftshadow" Fill="#40000000" Grid.Row="1" Grid.Column="0" Opacity="0">
                <Rectangle.Effect>
                  <BlurEffect Radius="3"/>
                </Rectangle.Effect>
              </Rectangle>            </Grid>          </Border>        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>
</ResourceDictionary>

Для этого теста я определил ViewModel с двумя логические свойства (Option1 и Option2). Одно из свойств имеет начальное значение false, другое - true.

Главное окно с двумя элементами управления CustomButton, связанными с двумя свойствами опции, а также двумя флажки, связанные с теми же свойствами.

Это я s полный код модели представления ...

using System;
using System.ComponentModel;
using System.Windows.Input;namespace VisualStateTest
{
  public class ViewModel : INotifyPropertyChanged
  {
    // Events for INotifyPropertyChanged
    public event PropertyChangedEventHandler PropertyChanged;    private bool        _option1 = false ;
    private bool        _option2 = true ;    public  ICommand    Notify1Command    { get; private set; }
    public  ICommand    Notify2Command    { get; private set; }    public ViewModel()
    {
      Notify1Command = new RelayCommand (new Action<object>(Execute_Notify1Command));
      Notify2Command = new RelayCommand (new Action<object>(Execute_Notify2Command));
    }    public bool Option1
    {
      get { return _option1 ; }
      set
      {
        _option1 = value ;
        NotifyPropertyChanged ( "Option1" ) ;
      }
    }    public bool Option2
    {
      get { return _option2 ; }
      set
      {
        _option2 = value ;
        NotifyPropertyChanged ( "Option2" ) ;
      }
    }    public void Execute_Notify1Command ( object value )
    {
      Option1 = !Option1 ;
    }    public void Execute_Notify2Command ( object value )
    {
      Option2 = !Option2 ;
    }    private void NotifyPropertyChanged ( String propertyName )
    {
      if ( this.PropertyChanged != null )
      {
        this.PropertyChanged ( this, new PropertyChangedEventArgs(propertyName) ) ;
      }
    }
  }
}

и главное окно ...

<Window x:Class="VisualStateTest.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:VisualStateTest"
        mc:Ignorable="d"
        WindowStartupLocation="CenterScreen"
        Title="MainWindow" Height="350" Width="525">  <Grid>
    <Grid.RowDefinitions>
      <RowDefinition Height="*"/>
      <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="*"/>
      <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>    <local:CustomButton Grid.Row="0" Grid.Column="0"
                        Command="{Binding Notify1Command}"
                        IsChecked="{Binding Option1, Mode=OneWay}"
                        Content="Option 1"
                        Margin="20"/>    <local:CustomButton Grid.Row="0" Grid.Column="1"
                        Command="{Binding Notify2Command}"
                        IsChecked="{Binding Option2, Mode=OneWay}"
                        Content="Option 2"
                        Margin="20"/>    <CheckBox Grid.Row="1" Grid.Column="0"
              IsChecked="{Binding Option1}"
              Content="Option 1"
              Margin="20 5"/>    <CheckBox Grid.Row="1" Grid.Column="1"
              IsChecked="{Binding Option2}"
              Content="Option 2"
              Margin="20 5"/>  </Grid></Window>

После того, как программа началось, щелкнув либо пользовательские кнопки, либо флажки, чтобы переключить параметр и показать или скрыть эффект тени.

Вот как это выглядит в "нормальном" состоянии:

Проблема заключается в том, что программа запускается. Несмотря на то, что Option2 инициализирован значением true, и была вызвана функция VisualStateManager.GoToState, эффект тени не отображается.

Это то, как он выглядит при запуске.

флажок справа указывает, что опция 2 верна, но эффект тени не присутствует.

что мне не хватает одного маленького кусочка головоломки. Если это поможет, я могу загрузить пример программы.

Извините, если это слишком много деталей.


0 ответов