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>
、チェックボックスはオプションをトグルし、影の効果を表示または非表示にします。
これは、「正常な」状態で次のようになります。
プログラムの起動時に問題があります。 Option2はtrueに初期化され、関数VisualStateManager.GoToStateが呼び出されていますが、シャドーエフェクトは表示されません。
これは起動時に見えるものです。
右側のチェックボックスは、オプション2が真であることを示しているが、影の効果は存在しません。
私はパズルの小さな断片が欠けていると確信しています。役立つ場合は、サンプルプログラムをアップロードできます。
これはあまりにも細かすぎると申し訳ありません。