不能动画'(0)。(1)'在不可变对象实例上

时间:2015-03-27 13:52:36

标签: wpf vb.net xaml

我有一个用户控件,我想在某些时候制作动画。我将两个用户控件添加到窗口。我在该窗口中使用一个按钮来启动动画。其中一个用户控件工作得很好。第二个给了我关于不可变对象实例错误的Can not animate'(0)。(1)'。我根本得不到这个!为什么一个工作而另一个工作?我正在阅读需要一个转换器 - 但我根本无法工作。我把代码留在这里以防万一我确实需要它。感谢您提供的任何帮助。我是WPF的新手,所以我可能会在这里做一些蠢事 - 请原谅我。这是我的usercontrol代码:

<UserControl x:Class="colorCompButton"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:Local="clr-namespace:UserControlTests"
         xmlns:custom="clr-namespace:UserControlTests"

         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" Height="179" Width="317">
<UserControl.Resources>
    <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
    <Storyboard x:Key="sb2" RepeatBehavior="Forever" x:Name="thisone">

        <ColorAnimation Storyboard.TargetName="badge1" 
      Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)" From="Red" To="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=BadgeColor}" 
      Duration="0:0:1" />

    </Storyboard>
</UserControl.Resources>

<Grid Margin="0,0,10,10">

    <Rectangle x:Name="rect"   HorizontalAlignment="Left" Height="135"  VerticalAlignment="Top" Width="259" x:FieldModifier="public"  Fill ="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=RectColor}"/>
    <Image x:Name="image" Height="87" Margin="10,10,63,0" VerticalAlignment="Top" x:FieldModifier="public" Source ="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=ImageSource}"/>


    <TextBlock x:Name="textBlock" Margin="0,102,10,38" Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=TxtBoxValue}" Background="Transparent" Foreground="White" FontSize="20" Padding="3"/>

    <Grid Margin="222,81,0,0" x:Name="NumberIMG" Height="78" VerticalAlignment="Top" HorizontalAlignment="Left" Width="85" Visibility="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=BadgeVisibile}" >
        <Border BorderBrush="Maroon" BorderThickness="1" CornerRadius="120" Background="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=BadgeColor}" HorizontalAlignment="Left" Height="76"  VerticalAlignment="Top" Width="76" x:Name="badge1" x:FieldModifier="public"></Border>
        <Border BorderBrush="black" Margin="2,2,0,0" BorderThickness="3" Opacity=".5" CornerRadius="120"  HorizontalAlignment="Left" Height="74"  VerticalAlignment="Top" Width="74"></Border>
        <Border BorderBrush="White" BorderThickness="3" CornerRadius="120"  HorizontalAlignment="Left" Height="78" VerticalAlignment="Top" Width="78">
            <Label x:Name="resCount" Content="46" FontSize="25"  Foreground="White"  HorizontalContentAlignment="center" VerticalContentAlignment="center" Margin="0,0,-3,-3"/>
        </Border>
    </Grid>

</Grid>

该控件背后的代码:

Imports System.Windows.Media.Animation

Public Class colorCompButton
Public Sub New()

    ' This call is required by the designer.
    InitializeComponent()

    ' Add any initialization after the InitializeComponent() call.

End Sub
'Public Shared Sub SetImage(obj As DependencyObject, value As ImageSource)
'    obj.SetValue(ImageProperty, value)
'End Sub
'Public Shared Function GetImage(obj As DependencyObject) As ImageSource
'    Return DirectCast(obj.GetValue(ImageProperty), ImageSource)
'End Function


Shared Sub New()
    'register attached dependency property

    Dim metadata = New FrameworkPropertyMetadata(DirectCast(Nothing, ImageSource))
    'ImageProperty = DependencyProperty.RegisterAttached("Image", GetType(ImageSource), GetType(colorCompButton), metadata)
End Sub


Public Shared ReadOnly BadgeVisibileProperty As DependencyProperty = DependencyProperty.Register("BadgeVisibile", GetType(Visibility), GetType(colorCompButton), New PropertyMetadata(Visibility.Visible))

Public Property BadgeVisibile() As Visibility
    Get
        Return DirectCast(GetValue(BadgeVisibileProperty), Visibility)
    End Get
    Set(value As Visibility)
        SetValue(BadgeVisibileProperty, value)
    End Set
End Property

Public Shared ReadOnly BadgeColorProperty As DependencyProperty = DependencyProperty.Register("BadgeColor", GetType(Brush), GetType(colorCompButton), New PropertyMetadata(New SolidColorBrush(Colors.DarkGray)))
Public Property BadgeColor() As SolidColorBrush
    Get
        Return DirectCast(GetValue(BadgeColorProperty), SolidColorBrush)
    End Get
    Set(value As SolidColorBrush)
        SetValue(BadgeColorProperty, value)
    End Set
End Property

Public Shared ReadOnly buttonColorProperty As DependencyProperty = DependencyProperty.Register("buttonColor", GetType(Brush), GetType(colorCompButton), New PropertyMetadata(New SolidColorBrush(Colors.DarkGray)))
Public Property buttonColor() As SolidColorBrush
    Get
        Return DirectCast(GetValue(buttonColorProperty), SolidColorBrush)
    End Get
    Set(value As SolidColorBrush)
        SetValue(buttonColorProperty, value)
    End Set
End Property


Public Shared ReadOnly ImageSourceProperty As DependencyProperty = DependencyProperty.Register("ImageSource", GetType(BitmapSource), GetType(colorCompButton))
Public Property ImageSource() As ImageSource
    Get
        Return DirectCast(GetValue(ImageSourceProperty), ImageSource)
    End Get
    Set(value As ImageSource)
        SetValue(ImageSourceProperty, value)
    End Set
End Property


Public Shared ReadOnly RectColorProperty As DependencyProperty = DependencyProperty.Register("RectColor", GetType(Brush), GetType(colorCompButton), New PropertyMetadata(New SolidColorBrush(Colors.DarkGray)))
Public Property RectColor() As SolidColorBrush
    Get
        Return DirectCast(GetValue(RectColorProperty), SolidColorBrush)
    End Get
    Set(value As SolidColorBrush)
        SetValue(RectColorProperty, value)
    End Set
End Property

Public Shared TxtBoxValueProperty As DependencyProperty = DependencyProperty.Register("txtBoxValue", GetType([String]), GetType(colorCompButton))
Public Property TxtBoxValue() As [String]
    Get
        Return DirectCast(GetValue(TxtBoxValueProperty), [String])
    End Get
    Set(value As [String])
        SetValue(TxtBoxValueProperty, value)
    End Set
End Property
Public Sub StartLeafUp()
    Dim sb As Storyboard = TryCast(Me.Resources("sb2"), Storyboard)
    sb.Begin()
End Sub

Public Sub StartLeafDown()
    Dim sb As Storyboard = TryCast(Me.Resources("sb2"), Storyboard)
    sb.Stop()
End Sub
End Class
Friend Class MyCloneConverter
Implements IValueConverter

Public Function Convert(value As Object, targetType As Type, parameter As Object, culture As Globalization.CultureInfo) As Object Implements IValueConverter.Convert
    If TypeOf value Is Freezable Then
        value = TryCast(value, Freezable).Clone()
    End If

    Return value
End Function

Public Function ConvertBack(value As Object, targetType As Type, parameter As Object, culture As Globalization.CultureInfo) As Object Implements IValueConverter.ConvertBack
    Throw New NotSupportedException()
End Function
End Class

主窗口和代码背后:

<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:UserControlTests" x:Class="MainWindow"
Title="MainWindow" Height="437" Width="1057">

<Grid>

    <local:colorCompButton x:Name="color" Margin="201,62,0,0"  VerticalAlignment="Top" HorizontalAlignment="Left" BadgeColor="#FF833E1D" buttonColor="Sienna" RectColor="Sienna" ImageSource="pack://siteoforigin:,,,/images/deviation.png" TxtBoxValue="I WORK"/>
    <Button x:Name="button" Content="WORKS FINE" HorizontalAlignment="Left" Margin="336,262,0,0" VerticalAlignment="Top" Width="160" Height="53"/>

    <Button x:Name="button1" Content="DOES NOT WORK!!" HorizontalAlignment="Left" Margin="534,262,0,0" VerticalAlignment="Top" Width="144" Height="53"/>
    <local:colorCompButton HorizontalAlignment="Left" Margin="534,62,0,0" VerticalAlignment="Top" BadgeColor="Indigo" RectColor="IndianRed" ImageSource="pack://siteoforigin:,,,/images/deviation.png" TxtBoxValue="I WON'T WORK" x:Name="res"/>
    <Label x:Name="label" Content="EXACT SAME CONTROLS.  WHY WILL THIS NOT WORK??" HorizontalAlignment="Left" Margin="375,365,0,0" VerticalAlignment="Top"/>

</Grid>

Imports System.Windows.Media.Animation

Class MainWindow

Private Sub button_Click(sender As Object, e As RoutedEventArgs) Handles button.Click
    color.StartLeafUp()


End Sub

Private Sub button1_Click(sender As Object, e As RoutedEventArgs) Handles button1.Click
    res.StartLeafUp()

End Sub
End Class

4 个答案:

答案 0 :(得分:2)

这可能不是最佳答案,但我通过添加另一个边框,将其背景设置为透明并将其设置为动画而不是第一个边框来自行解决此问题。这看起来更像是一个黑客而不是解决方案,但它确实有效。我仍然愿意听到一个真正的解决方案 - 如果有人有。

答案 1 :(得分:1)

我在尝试动画TextBlock Foreground属性时遇到了同样的错误/问题。

一种解决方法是创建Color类型DependencyProperty并将其设置为颜色动画的目标。然后,例如,将TextBlock Foreground属性绑定到托管UserControl(或Window)的DependencyProperty,并使用转换器从Color创建Brush。

以下是我命名为SpectrumTextBlock的闪烁TextBlock示例,它在加载控件时启动动画:

XAML:

<UserControl x:Class="Common.SpectrumTextBlock"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         xmlns:local="clr-namespace:Common"
         mc:Ignorable="d"
         x:Name="spectrumTextBlock">

<UserControl.Resources>

    <local:ColorToBrushConverter x:Key="colorToBrushConverter"/>

    <Storyboard x:Key="spectrumStoryboard" RepeatBehavior="Forever">
        <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(EffectColor)" Storyboard.TargetName="spectrumTextBlock">
            <EasingColorKeyFrame KeyTime="0" Value="Black"/>
            <EasingColorKeyFrame KeyTime="0:0:0.1" Value="Red"/>
            <EasingColorKeyFrame KeyTime="0:0:0.2" Value="Orange"/>
            <EasingColorKeyFrame KeyTime="0:0:0.3" Value="Yellow"/>
            <EasingColorKeyFrame KeyTime="0:0:0.4" Value="Green"/>
            <EasingColorKeyFrame KeyTime="0:0:0.5" Value="Cyan"/>
            <EasingColorKeyFrame KeyTime="0:0:0.6" Value="Blue"/>
            <EasingColorKeyFrame KeyTime="0:0:0.7" Value="Violet"/>
        </ColorAnimationUsingKeyFrames>
    </Storyboard>

</UserControl.Resources>

<TextBlock Text="TEST TEXT" Foreground="{Binding ElementName=spectrumTextBlock, Path=EffectColor, Converter={StaticResource colorToBrushConverter}}"/>

此控件的CS文件包含转换器:

using System;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Animation;

namespace Common
{
public partial class SpectrumTextBlock : UserControl
{
    private Storyboard _effestStoryboard;

    public Color EffectColor
    {
        get { return (Color)GetValue(EffectColorProperty); }
        set { SetValue(EffectColorProperty, value); }
    }

    public static readonly DependencyProperty EffectColorProperty =
        DependencyProperty.Register("EffectColor", typeof(Color), typeof(SpectrumTextBlock), new PropertyMetadata(SystemColors.ControlTextColor));

    public SpectrumTextBlock()
    {
        InitializeComponent();
        this.Loaded += SpectrumTextBlock_Loaded;
    }

    private void SpectrumTextBlock_Loaded(object sender, RoutedEventArgs e)
    {
        _effestStoryboard = (Storyboard)FindResource("spectrumStoryboard");
        _effestStoryboard.Begin();
    }
}

internal class ColorToBrushConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return new SolidColorBrush((Color)value);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

}

另一种解决方法是使用0px大小(不可见)Rectangle并为Fill属性设置动画,然后将TextBlock Foreground属性绑定到Rectangle的Fill属性。但是第一个DependencyProperty解决方法看起来不那么严重&#34; hacky&#34;。

答案 2 :(得分:0)

任何遇到问题的人:

  

无法在不可变对象实例上为'(0)。(1)'设置动画

添加[VisualState x:Name="Normal"]解决了该问题。

下面的代码是一个示例:

XAML:

<Style TargetType="RadioButton">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="RadioButton">
                <Border x:Name="borderIn" 
                        CornerRadius="0">
                    <Label>
                        <ContentPresenter/>
                    </Label>
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="CommonStates">
                            <VisualState x:Name="Normal">
                                <Storyboard>
                                    <ColorAnimation Storyboard.TargetName="borderIn" 
                                                    Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"
                                                    FillBehavior="HoldEnd" Duration="0"/>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="MouseOver">
                                <Storyboard>
                                    <ColorAnimation To="LightBlue" Storyboard.TargetName="borderIn" 
                                                    Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"
                                                    FillBehavior="HoldEnd" Duration="0"/>
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                        <VisualStateGroup x:Name="CheckStates">
                            <VisualState x:Name="Unchecked">
                                <Storyboard>
                                    <ColorAnimation Storyboard.TargetName="borderIn" 
                                                    Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"
                                                    FillBehavior="HoldEnd" Duration="0"/>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="Checked">
                                <Storyboard>
                                    <ColorAnimation Storyboard.TargetName="borderIn" 
                                                    Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"
                                                    FillBehavior="HoldEnd" Duration="0"/>
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsChecked" Value="true">
                        <Setter Property="Background" TargetName="borderIn" Value="LightCyan" />
                    </Trigger>
                    <Trigger Property="IsChecked" Value="false">
                        <Setter TargetName="borderIn" Property="Background" Value="Transparent"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

希望此解决方案可以帮助遇到相同问题的人

答案 3 :(得分:0)

对我来说,原因是我正在这样做:

Background="{Binding ElementName=ToggleButton, Path=Background}"

而不是:

Background="{TemplateBinding Background}"

在我正在控件模板内制作动画的控件上。

似乎您有相同的错误:-)

相关问题