2017-12-08 11 views
0

VisualStateManagerを使用してカスタムコントロールに問題があります。VisualStateの初期値を設定する

状態間の遷移は予想どおりですが、初期状態の設定方法はわかりません。

私はこの問題を説明する完全な例を作りました。 この例では、ButtonBaseに基づくカスタムコントロールを使用しています。

コントロールには、「チェック済み」と「未チェック」の2つの状態を持つ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プロパティが設定されているときに、左側と上側に影を表示します。

(私はデザインが悪いことを知っているが、これはグラフィカルなデザインについての質問ではありません。)

これはコントロールテンプレートです:私はViewModelにと定義した。この試験では

<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> 

2つのブール値のプロパティ(Option1とOption2)。 プロパティの1つに初期値falseがあり、もう一方がtrueです。

メインウィンドウには、2つのオプションプロパティに接続された2つのカスタムボタンコントロールと、同じプロパティに接続された2つのチェックボックスがあります。カスタムボタンまたはいずれかをクリック

これは、ビューモデルの完全なコードです...

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> 

、チェックボックスはオプションをトグルし、影の効果を表示または非表示にします。

これは、「正常な」状態で次のようになります。

enter image description here

プログラムの起動時に問題があります。 Option2はtrueに初期化され、関数VisualStateManager.GoToStateが呼び出されていますが、シャドーエフェクトは表示されません。

これは起動時に見えるものです。

enter image description here

右側のチェックボックスは、オプション2が真であることを示しているが、影の効果は存在しません。

私はパズルの小さな断片が欠けていると確信しています。役立つ場合は、サンプルプログラムをアップロードできます。

これはあまりにも細かすぎると申し訳ありません。

答えて

0

私は答えを見つけたと思います。

カスタムコントロールでOnApplyTemplate()関数をオーバーライドする必要があります。私は、次の機能を備えたCustomButtonクラスのコードを拡張しています

public override void OnApplyTemplate() 
{ 
    base.OnApplyTemplate(); 

    if (IsChecked) 
    { 
    VisualStateManager.GoToState(this, "Checked", true); 
    } 
    else 
    { 
    VisualStateManager.GoToState(this, "Unchecked", true); 
    } 
} 

私はMicrosoft documentationを読み取ることによって、この情報を見つけました。メソッドOnApplyTemplateを参照して、それは状態を示します

ControlTemplateのFrameworkElementがコントロールで使用できる最も早いものです。

関連する問題