2

我有一个 UserControl,其中包含一个带有自定义 ItemsPanel 的 ItemsControl,具有一个名为“MaxColumns”的依赖项属性。我想定义一个 VisualState(在 UserControl 级别),它可以为自定义面板上的“MaxColumns”属性设置动画。

本质上,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”,则会收到有关名称范围的错误(可能是因为“MyCoolPanel”不在 LayoutRoot 的名称范围内)。我不知道是否有办法限定“TargetName”中的名称范围?

有人对此有解决方案吗?在不诉诸自定义附加属性的情况下,这似乎是可行?我的意思是,我不反对附加属性,但我觉得您应该能够直接在 XAML 中执行此操作?

4

1 回答 1

3

好的,确实ItemsPanel不是一个真实的对象,而是一个模板,将使用它来创建对象。所以从技术上讲,你的参考是行不通的。

关于实施,我有以下几点:

  1. 您在 ItemsPanel(无论如何都是模板)上设置了一些附加属性,但在 ItemsControl 本身上设置了一些附加属性。
  2. CoolPanel使用 将 的 MaxColumns 绑定到该附加属性RelativeSource FindAncestor

好吧,你可以省略附加的属性,并使用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>
于 2011-07-13T18:28:54.707 回答