2010-03-07 2 views
3

У меня есть два Визуальных государств, определенных в моем MainWindow в LayoutRoot сетке следующим образом:WPF - Манипулирование VisualState от UserControl

<Grid x:Name="LayoutRoot" Background="#FF434343" ShowGridLines="True"> 

<Grid.RowDefinitions> 
    <RowDefinition Height="100"/> 
    <RowDefinition Height="*"/> 
</Grid.RowDefinitions> 


    <VisualStateManager.CustomVisualStateManager> 
     <ic:ExtendedVisualStateManager/> 
    </VisualStateManager.CustomVisualStateManager> 
    <VisualStateManager.VisualStateGroups> 
     <VisualStateGroup x:Name="VisualStateLogin"> 
      <VisualStateGroup.Transitions> 
       <VisualTransition GeneratedDuration="00:00:00.6000000"/> 
      </VisualStateGroup.Transitions> 
      <VisualState x:Name="LoggedOn"> 
       <Storyboard> 
        <ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="{x:Null}" Storyboard.TargetProperty="(Window.WindowStyle)"> 
         <DiscreteObjectKeyFrame KeyTime="00:00:00" Value="{x:Static WindowStyle.None}"/> 
        </ObjectAnimationUsingKeyFrames> 
        <BooleanAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="{x:Null}" Storyboard.TargetProperty="(Window.AllowsTransparency)"> 
         <DiscreteBooleanKeyFrame KeyTime="00:00:00" Value="True"/> 
        </BooleanAnimationUsingKeyFrames> 
       </Storyboard> 
      </VisualState> 
      <VisualState x:Name="LoggedOff"> 
       <Storyboard> 
        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="brdContent" Storyboard.TargetProperty="(UIElement.Opacity)"> 
         <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0.1"/> 
        </DoubleAnimationUsingKeyFrames> 
        <BooleanAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="brdContent" Storyboard.TargetProperty="(UIElement.IsEnabled)"> 
         <DiscreteBooleanKeyFrame KeyTime="00:00:00" Value="False"/> 
        </BooleanAnimationUsingKeyFrames> 
        <BooleanAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="ucTabButtons" Storyboard.TargetProperty="(UIElement.IsEnabled)"> 
         <DiscreteBooleanKeyFrame KeyTime="00:00:00" Value="False"/> 
        </BooleanAnimationUsingKeyFrames> 
        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="ucTabButtons" Storyboard.TargetProperty="(UIElement.Opacity)"> 
         <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0.4"/> 
        </DoubleAnimationUsingKeyFrames> 
       </Storyboard> 
      </VisualState> 
     </VisualStateGroup> 
    </VisualStateManager.VisualStateGroups> 

Он отлично работает переключение из одного состояния в другое thoughtout в коде MainWindow, как это:

void MainWindow_Loaded(object sender, RoutedEventArgs e) 
    { 
     //ExtendedVisualStateManager.GoToElementState(this.LayoutRoot as FrameworkElement, "LoggedOff", false);   
    } 

Но теперь, мне нужно, чтобы иметь возможность переключения состояния из UserControl внутри MainWindow ...

Я судимое что:

private void btnOk_Click(object sender, System.Windows.RoutedEventArgs e) 
    { 
     MainWindow parent = new MainWindow(); 
     Grid root = new Grid(); 
     root = (Grid)parent.FindName("LayoutRoot"); 
     ExtendedVisualStateManager.GoToElementState(root as FrameworkElement, "LoggedOn", true); 
    } 

И это дает мне следующее исключение:

System.NullReferenceException было необработанное Message = «ссылка на объект не указывает на экземпляр объекта.» Источник = "WPFToolkit"

Кто-нибудь знает, как переключать состояния с пользовательского контроля?

ThankYou,

Josi

ответ

1

Я рекомендую определение интерфейса для переключения между состояниями. Форма может реализовать интерфейс, и он может либо явно передать интерфейс в элемент управления, либо элемент управления может запросить его родительский элемент, чтобы увидеть, реализован ли интерфейс. Таким образом, пользовательский элемент управления не жестко связан с его контейнером, а только с тем поведением, которое он ожидает от контейнера.

На боковой ноте, с пользовательским управлением, изменение состояния его контейнера является необычным дизайном. Возможно, вам стоит подумать, есть ли альтернативный способ структурирования требования.

Возможный интерфейс:

public interface IStateChanger 
{ 
    void GoToElementState(string state);  
} 

Вы можете иметь свой MainWindow реализовать этот интерфейс:

void IStateChanger.GoToElementState(string state) 
    { 
     ExtendedVisualStateManager.GoToElementState(this.LayoutRoot as FrameworkElement, state, false);   
    } 

Тогда ваш контроль, следуя вашему примеру, может сделать это:

private void btnOk_Click(object sender, System.Windows.RoutedEventArgs e) 
    { 
     MainWindow parent = new MainWindow(); 
     if (parent is IStateChanger) 
      ((IStateChanger)parent).GoToElementState("LoggedOn"); 
    } 
0

Создайте публичное событие в вашем пользовательском элементе управления, которому может подписаться родитель; событие может затем использоваться как триггер для перехода состояния.

Смежные вопросы