dtm
dtm

Reputation: 792

Is there a way to assign a binding to a value rather than bind the value in XAML?

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

Answers (1)

norekhov
norekhov

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.

  1. Every Storyboard will have to maintain this Binding.
  2. When running this Storyboard actually the current value of Foo will be set to SomeProperty. Latter changes in Foo won't be affected.

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

Related Questions