Лучший способ распространения изменений VisualState - PullRequest
1 голос
/ 20 августа 2010

В настоящее время я сталкиваюсь со сценарием, в котором я не уверен, что является лучшим способом обработки.

Сценарий:

  1. ControlA имеет 2 двух пользовательских визуальных состояниядавайте назовем их «StateOn» и «StateOff».
  2. Теперь я применяю шаблон к ControlA, давайте назовем его «templateA».
  3. «templateA» имеет один элемент управления типа ControlB(кто не знает о StateOn / Off).
  4. ControlB имеет шаблон, который обрабатывает изменения визуального состояния ControlA, а именно StateOn и StateOff.

Проблема:
ControlB не получает изменений в VisualStates, запущенных на ControlA, поэтому никаких визуальных изменений не происходит.

Я думаю, что проблема связана с корневым элементом, являющимся элементом управления (ControlB), который не запускаетсяgotostate на желаемые состояния.Однако мне интересно, каков самый простой / чистый способ распространения изменений визуального состояния ControlA в ControlB.

Спасибо за вашу помощь!

Генри

Xaml: -

<UserControl x:Class="VisualStateChangePropagation.MainPage"
    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:VisualStateChangePropagation"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">

    <Grid x:Name="LayoutRoot" Background="White">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="20"/>
            <ColumnDefinition Width="50"/>
            <ColumnDefinition Width="20"/>
        </Grid.ColumnDefinitions>
        <Grid.Resources>

            <SolidColorBrush x:Name="Fill_Bg_Red" Color="Red"/>
            <SolidColorBrush x:Name="Fill_Bg_Blue" Color="Blue"/>

            <ControlTemplate x:Name="templateA" TargetType="Control">
                <Grid>
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="Common">
                            <VisualState x:Name="StateOn">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="m_rect"
                                                                   Storyboard.TargetProperty="(Rectangle.Fill)">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource Fill_Bg_Red}" />
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="StateOff"/>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                    <Rectangle x:Name="m_rect" Fill="{StaticResource Fill_Bg_Blue}"/>
                </Grid>
            </ControlTemplate>

            <ControlTemplate x:Name="templateB" TargetType="Control">
                <local:ControlB Template="{StaticResource templateA}"/>
            </ControlTemplate>

        </Grid.Resources>
        <local:ControlA x:Name="m_control1" Template="{StaticResource templateA}" Grid.Column="0"/>
        <Button Click="Button_Click" Grid.Column="1" Content="swap"/>
        <local:ControlA x:Name="m_control2" Template="{StaticResource templateB}" Grid.Column="2"/>
    </Grid>
</UserControl>

код сзади:

public class ControlA : Control
{
    public void ToggleState()
    {
        m_isSet = !m_isSet;
        UpdateVisualState();
    }

    private void UpdateVisualState()
    {
        string targetState = m_isSet ? "StateOn" : "StateOff";
        VisualStateManager.GoToState(this, targetState, false);
    }

    private bool m_isSet = false;
}

public class ControlB : Control
{

}

1 Ответ

0 голосов
/ 20 августа 2010

Прежде всего, ControlA и ControlB должны иметь свойство зависимости для IsSet.

    public bool IsSet
    {
        get { return (bool)GetValue(IsSetProperty); }
        set { SetValue(IsSetProperty, value); }
    }

    public static readonly DependencyProperty IsSetProperty =
            DependencyProperty.Register(
                    "IsSet",
                    typeof(bool),
                    typeof(ControlA),  //Change in ControlB
                    new PropertyMetadata(false, OnIsSetPropertyChanged));

    private static void OnIsSetPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        Control source = d as Control;
         string newState = (bool)e.NewValue ? "StateOn" : "StateOff";
         VisualStateManager.GotoState(source, newState, true);
    }

Вопреки вашей интуиции визуальные состояния вообще не распространяются. Состояния имеют значение только для контроля, к которому они непосредственно привязаны. Однако с помощью этого свойства зависимости, добавленного к обоим элементам управления, теперь вы можете распространять значение свойства через привязку шаблона: -

        <ControlTemplate x:Name="templateB" TargetType="Control">
            <local:ControlB Template="{StaticResource templateA}" IsSet="{TemplateBinding IsSet}" />
        </ControlTemplate>

Что касается вашего исходного кода ControlA, поле m_isSet больше не требуется: -

public void ToggleState()
{
    IsSet = !IsSet;
}
...