2010-08-19 66 views
1

我目前正面臨一個場景,我不確定什麼是最好的處理方式。傳播VisualState更改的最佳方式

場景:

  1. ControlA有2個兩個自定義visualstates,我們姑且稱之爲「StateOn」和「StateOff」。
  2. 我現在在ControlA上應用一個模板,我們稱它爲「templateA」。
  3. 「templateA」在ControlB下有一個控件(誰不知道StateOn/Off)。
  4. ControlB具有處理ControlA的視覺狀態變化的模板,即StateOn和StateOff。

問題:
ControlB沒有收到更改VisualStates射擊ControlA,因此沒有視覺上的變化發生。

我認爲這個問題與根元素是一個控件(ControlB)有關,它不會在所需的狀態下觸發gotostate。不過,我想知道將ControlA的VisualState更改傳播給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> 

後面的代碼:

所有都ControlA和ControlB的
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 
{ 

} 
+0

歡迎至此,請花幾分鐘時間閱讀常見問題解答和Markdown文檔(在編輯問題時可在右側空白處找到有用的synposis)。 – AnthonyWJones 2010-08-19 20:51:07

回答

0

首先應該有一個依賴屬性爲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; 
}