M.S
M.S

Reputation: 1610

Very strange problem in Silverlight with XAML, custom property and animation

I created a custom user control that has a property of type Storyboard. Something like:

public class UC : UserControl
{
    public static readonly DependencyProperty AnimationProperty = DependencyProperty.Register(
        "Animation",
        typeof(Storyboard),
        typeof(UC),
        null);

    public Storyboard Animation
    {
        get { return (Storyboard)GetValue(AnimationProperty); }
        set { SetValue(AnimationProperty, value); }
    }

    public UC()
    {
        this.Loaded += new RoutedEventHandler(UC_Loaded);
    }

    private void UC_Loaded(object sender, RoutedEventArgs e)
    {
        if (this.Animation != null)
        {
            this.Animation.Begin();
        }
    }
}

In XAML I used it as follows:

<loc:UC x:Name="uc" Opacity="0" >
    <TextBlock FontSize="50">Some text</TextBlock>
    <loc:UC.Animation>
        <Storyboard>
            <DoubleAnimation Storyboard.TargetName="uc" Storyboard.TargetProperty="Opacity" To="0.5" Duration="0:0:1" />
        </Storyboard>
    </loc:UC.Animation>
</loc:UC>

So far so good.

Later on I decided that I needed another item along with the storyboard. So I changed the code to accept a custom object that contains the storyboard and another piece of information. Something like:

public class UC : UserControl
{
    public static readonly DependencyProperty AnimationProperty = DependencyProperty.Register(
        "Animation",
        typeof(AnimationHolder),
        typeof(UC),
        null);

    public AnimationHolder Animation
    {
        get { return (AnimationHolder)GetValue(AnimationProperty); }
        set { SetValue(AnimationProperty, value); }
    }

    public UC()
    {
        this.Loaded += new RoutedEventHandler(UC_Loaded);
    }

    private void UC_Loaded(object sender, RoutedEventArgs e)
    {
        if (this.Animation != null)
        {
            this.Animation.Animation.Begin();
        }
    }
}

public class AnimationHolder
{
    public Storyboard Animation
    {
        get;
        set;
    }

    public int OtherValue
    {
        get;
        set;
    }
}

And used it in XAML:

<loc:UC x:Name="uc" Opacity="0" >
    <TextBlock FontSize="50">Some text</TextBlock>
    <loc:UC.Animation>
        <loc:AnimationHolder OtherValue="20">
            <loc:AnimationHolder.Animation>
                <Storyboard>
                    <DoubleAnimation Storyboard.TargetName="uc" Storyboard.TargetProperty="Opacity" To="0.5" Duration="0:0:0" />
                </Storyboard>
            </loc:AnimationHolder.Animation>                            
        </loc:AnimationHolder>
    </loc:UC.Animation>
</loc:UC>

However, now when I try to begin the animation I get an InvalidOperationException with the message: "Cannot resolve TargetName uc."

Anyone has an idea why?

I know that in this example I can work around the problem by not using a custom object, and using another property instead. However this is a simplified version of my scenario, which focuses at the problem. In the real scenario I must use a custom object.

Upvotes: 0

Views: 367

Answers (1)

Sarfaraz Nawaz
Sarfaraz Nawaz

Reputation: 361442

Two things need to be done with your new approach:

  • In AnimationHolder class, make Animation property a dependency property, just like it previously was.
  • Derive AnimationHolder class from DependencyObject. This is necessary so that you can make Animation a dependency property. Please remember that only classes deriving from DependencyObject can define dependency properties!

I think once you do these two things, it'll solve your problem!

Upvotes: 1

Related Questions