I have a UserControl that contains an ItemsControl with a custom ItemsPanel, with a dependency property called "MaxColumns". I'd like to define a VisualState (at the UserControl level) that can animate the "MaxColumns" property on t开发者_如何学Che custom panel.
In essence, the XAML looks something like:
<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>
However, I cannot for the life of me figure out what the right syntax is for the animation? If I use the syntax shown above, I get the error: "'ItemsPanel' property does not point to a DependencyObject in path '(0).(1)'". I'm presuming this is because it's technically pointing to a ItemsPanelTemplate?
If I refer to "MyCoolPanel" directly in the Storyboard.TargetName property, I get an error about Name scope (presumably because "MyCoolPanel" isn't in the namescope of LayoutRoot). I don't know if there is a way to qualify name scope in "TargetName"?
Does anyone have a solution for this? It seems like something that should be doable without resorting to custom attached properties? I mean, I'm not opposed to attached properties, but I feel like you ought to be able to do this directly in the XAML?
Okay, indeed the ItemsPanel
is not a real object but a template with which the object is going to be created. So technically your reference is not going to work.
I've got the following about implementation:
- you set some attached property on the ItemsPanel (which is anyway a template), but on the ItemsControl itself.
- You bind the
CoolPanel
's MaxColumns to that attached property usingRelativeSource FindAncestor
.
Well, you could omit the attached property, and use Tag
for it :-) Indeed, the ItemsControl
is totally in your control, so there is no crime in abusing the Tag
a little bit.
So the code would be like this:
<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>
精彩评论