VisualStateManager를 사용하는 사용자 정의 컨트롤에 문제가 있습니다.VisualState의 초기 값 설정
상태 전환은 예상대로 작동하지만 초기 상태 설정 방법을 이해하지 못합니다.
나는이 문제를 설명하기 위해 완전한 예를 제시했다. 이 예제에서는 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>
두 개의 부울 속성 (Option1 및 Option2). 속성 중 하나에 초기 값 false가 있고 다른 하나는 true입니다.
두 개의 Custom Properties 컨트롤에 연결된 두 개의 CustomButton 컨트롤과 동일한 속성에 연결된 두 개의 확인란이있는 주 창이 있습니다. 사용자 정의 버튼 또는 중 하나를 클릭
이 뷰 모델의 전체 코드입니다 ...
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 함수가 호출되었지만 그림자 효과는 표시되지 않습니다.
이것은 시작시의 모습입니다.
오른쪽에있는 체크 박스에 해당 옵션이 사실을 나타냅니다 만, 그림자 효과는 존재하지 않습니다.
저는 퍼즐의 작은 조각 하나가 빠졌다고 확신합니다. 도움이된다면 샘플 프로그램을 업로드 할 수 있습니다.
너무 자세히 설명해 주시면 죄송합니다.