Reputation: 792
So, let's say I want to modify the DataContext of several visual elements in a dynamic fashion and that I want to do so as part of a Storyboard. I might do that like so:
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SomeVisualElement" Storyboard.TargetProperty="(FrameworkElement.DataContext)" Duration="0:0:0" >
<DiscreteObjectKeyFrame KeyTime="0:0:0" >
<DiscreteObjectKeyFrame.Value>
<Binding Path="Repository.GeneratedThings[0].Element" />
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
This has the effect of binding the Value of the DiscreteObjectKeyFrame to Repository.GeneratedThings[0].Element. When this Storyboard is applied, the DataContext of SomeVisualElement is set to Repository.GeneratedThings[0].Element. This is the equivalent, I think, of saying:
<UserControl x:Name="SomeVisualElement" DataContext="{Binding Path="Repository.GeneratedThings[0].Element"} />
This is functional, but what I'd like to do would be to have some way that the binding is maintained only in the visual element but not in the key frame. We have few visual elements but many Storyboards and KeyFrames, and we notice a performance hit proportional to the number of KeyFrames when, e.g., we update the GeneratedThings object (not the individual elements of the collection).
How can I set up the DiscreteObjectKeyFrame so that the DataContext ends up bound correctly but that the value of the DiscreteObjectKeyFrame isn't bound? Is this even a reasonable semantic distinction in the context of WPF/XAML between a value being a Binding and a value being bound?
Alternatively, is there another way to change the DataContext of several visual elements from within a Storyboard and that doesn't involve having each Storyboard maintaining a binding?
Upvotes: 2
Views: 1918
Reputation: 4233
Imagine that you have the following code:
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SomeVisualElement" Storyboard.TargetProperty="SomeProperty" Duration="0:0:0" >
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value={Binding Foo} />
</ObjectAnimationUsingKeyFrames>
One should notice two problems here.
I suggest the following. Create some dependency object with Foo as dependency property. For example:
<Grid.Resources>
<viewModel:FooContainer Foo={Binding Foo} x:Key="FooContainer" />
</Grid.Resources>
Use this container in Storyboard(s).
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SomeVisualElement" Storyboard.TargetProperty="SomeProperty" Duration="0:0:0" >
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value={StaticResource FooContainer} />
</ObjectAnimationUsingKeyFrames>
Modify ContentTemplate of a Control so you can bind to Foo property itself. Thus you can transfer binding and not value of Foo directly to a Control. Also Storyboard won't be affected by Foo value change.
Upvotes: 3