2011-07-13 28 views
2

我有一個UserControl,它包含帶有自定義ItemsPanel的ItemsControl和一個名爲「MaxColumns」的依賴項屬性。我想定義一個VisualState(在UserControl級別),可以在自定義面板上設置「MaxColumns」屬性的動畫效果。WPF VisualStateManager - 如何在模板化子內動畫屬性

從本質上講,XAML看起來像:

<Grid x:Name="LayoutRoot"> 
    <VisualStateManager.VisualStateGroups> 
    <VisualStateGroup x:Name="MyCoolState"> 
     <VisualState x:Name="Normal" /> 
     <VisualState x:Name="NotNormal"> 
     <Storyboard> 
      <Int32Animation Duration="0" 
          Storyboard.TargetName="Details" 
          Storyboard.TargetProperty="(ItemsControl.ItemsPanel).(local:CoolPanel.MaxColumns)" 
          To="4" /> 
     </Storyboard> 
     </VisualState> 
    </VisualStateGroup> 
    <VisualStateManager> 
    <ItemsControl x:Name="Details"> 
    <ItemsControl.ItemsPanel> 
     <ItemsPanelTemplate> 
     <local:CoolPanel x:Name="MyCoolPanel" 
         MaxColumns="1" /> 
     </ItemsPanelTemplate> 
    </ItemsControl.ItemsPanel> 
    </ItemsControl> 
</Grid> 

但是,我不能爲我的生命找出正確的語法是什麼樣的動畫呢?如果我使用上面顯示的語法,我得到錯誤:「'ItemsPanel'屬性不指向路徑'(0)。(1)'」中的DependencyObject。我假設這是因爲它技術上指向一個ItemsPanelTemplate?

如果我直接在Storyboard.TargetName屬性中引用「MyCoolPanel」,則會收到有關Name範圍的錯誤(大概是因爲「MyCoolPanel」不在LayoutRoot的名稱範圍中)。我不知道是否有方法限定「TargetName」中的名稱範圍?

有沒有人有解決方案?這似乎是是可行的,而不訴諸自定義附加屬性?我的意思是,我不反對附加屬性,但是我覺得你應該能夠直接在XAML中執行此操作?

+0

您的XAML代碼是一些控件模板的一部分,對不對? – Vlad

+0

實際上它是UserControl的一部分。 「LayoutRoot」網格是UserControl的根控件。 – Jordan0Day

回答

3

好吧,的確,ItemsPanel不是一個真實的物體,而是一個用來創建物體的模板。所以從技術上講,你的參考是行不通的。

我有以下有關執行:

  1. 設置在ItemsPanel一些附加屬性(這無論如何是一個模板),但在ItemsControl的本身。
  2. 您使用RelativeSource FindAncestorCoolPanel的MaxColumns綁定到該附加屬性。

嗯,你可以省略附加屬性,並使用Tag它的確,ItemsControl是完全在你的控制:-),所以在濫用Tag一點點沒有犯罪。

因此,代碼會是這樣:

<Grid x:Name="LayoutRoot"> 
    <VisualStateManager.VisualStateGroups> 
    <VisualStateGroup x:Name="MyCoolState"> 
     <VisualState x:Name="Normal" /> 
     <VisualState x:Name="NotNormal"> 
     <Storyboard> 
      <Int32Animation Duration="0" 
          Storyboard.TargetName="Details" 
          Storyboard.TargetProperty="Tag" 
          To="4" /> 
     </Storyboard> 
     </VisualState> 
    </VisualStateGroup> 
    <VisualStateManager> 
    <ItemsControl x:Name="Details" Tag="3"> 
    <ItemsControl.ItemsPanel> 
     <ItemsPanelTemplate> 
     <local:CoolPanel 
      MaxColumns="{Binding Tag, RelativeSource={RelativeSource FindAncestor, 
              AncestorType=ItemsControl}}" /> 
     </ItemsPanelTemplate> 
    </ItemsControl.ItemsPanel> 
    </ItemsControl> 
</Grid> 
+0

這是一個非常聰明的黑客攻擊,我沒有想過使用標記來降低價值。不過,我想我可能更喜歡在CoolPanel類中定義一個附加屬性並使用它。不過,如果沒有其他人提出任何問題,我會將其標記爲答案。 – Jordan0Day