2011-05-02 96 views
2

(這是用不同的方式來解決my earlier problem的嘗試。)結合WPF DataTriggers和故事板代碼

我創建它使用我希望能夠通過設置動畫放射漸變畫筆的用戶控件在我的視圖模型上的一個屬性。漸變畫筆也有一些綁定到視圖模型的屬性。

的XAML用戶控件是(一些性質剪斷爲了簡潔):

<UserControl x:Class="WpfApplication1.AnimatedLineArrow" 
      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:Controls="clr-namespace:Microsoft.Expression.Controls;assembly=Microsoft.Expression.Drawing" 
      mc:Ignorable="d" d:DesignHeight="150" d:DesignWidth="300" 
      Name="animatedLineArrow"> 
    <Grid> 
     <Controls:LineArrow x:Name="ArrowControl" 
      StartCorner="{Binding ElementName=animatedLineArrow, Path=StartCorner, FallbackValue=TopRight}" 
      Width="{Binding ElementName=animatedLineArrow, Path=Width, FallbackValue=200}" 
      Height="{Binding ElementName=animatedLineArrow, Path=Height, FallbackValue=200}" 
      <Controls:LineArrow.Stroke> 
       <RadialGradientBrush RadiusX="0.2" RadiusY="1.0" 
            Center="{Binding ElementName=animatedLineArrow, Path=StartPoint, Mode=OneWay}" 
            GradientOrigin="{Binding ElementName=animatedLineArrow, Path=StartPoint, Mode=OneWay}"> 
        <RadialGradientBrush.GradientStops> 
         <GradientStop Color="{Binding ElementName=animatedLineArrow, Path=HighlightColour, Mode=OneWay, FallbackValue=Cyan}" Offset="0.0" /> 
         <GradientStop Color="{Binding ElementName=animatedLineArrow, Path=PrimaryColour, Mode=OneWay, FallbackValue=Navy}" Offset="1.0" /> 
        </RadialGradientBrush.GradientStops> 
       </RadialGradientBrush> 
      </Controls:LineArrow.Stroke> 
     </Controls:LineArrow> 
    </Grid> 
</UserControl> 

代碼隱藏設置的各種依賴屬性,以及該控件的Loaded事件,定義了一個故事板進行動畫顯示放射漸變的中心和漸變原點屬性,然後確定應該對那些依賴屬性之一的值響應DataTriggers:

private void ConfigureAnimation(object sender, EventArgs e) 
{ 
    StartPoint = StartingPoints[StartCorner]; 
    EndPoint = EndingPoints[StartCorner]; 

    AnimatedLineArrow arrow = (AnimatedLineArrow)sender; 
    Storyboard storyboard = CreateStoryboard(arrow); 

    DataTrigger startTrigger = new DataTrigger 
            { 
             Binding = new Binding 
                { 
                 Path = new PropertyPath(IsRunningProperty), 
                 RelativeSource = RelativeSource.Self 
                }, 
             Value = true 
            }; 
    startTrigger.EnterActions.Add(new BeginStoryboard { Storyboard = storyboard, Name = "beginStoryboard" }); 

    DataTrigger endTrigger = new DataTrigger 
           { 
            Binding = new Binding 
                { 
                 Path = new PropertyPath(IsRunningProperty), 
                 RelativeSource = RelativeSource.Self 
                }, 
            Value = false 
           }; 
    endTrigger.EnterActions.Add(new StopStoryboard { BeginStoryboardName = "beginStoryboard" }); 

    Style style = new Style(typeof(AnimatedLineArrow)); 
    style.Triggers.Add(startTrigger); 
    style.Triggers.Add(endTrigger); 
    arrow.Style = style; 
} 

private Storyboard CreateStoryboard(AnimatedLineArrow arrow) 
{ 
    Storyboard storyboard = new Storyboard(); 

    PointAnimation originAnimation = new PointAnimation(StartingPoints[StartCorner], EndingPoints[StartCorner], Duration, FillBehavior.HoldEnd); 
    PointAnimation centreAnimation = originAnimation.Clone(); 

    Storyboard.SetTarget(originAnimation, arrow); 
    Storyboard.SetTargetProperty(originAnimation, new PropertyPath(RadialGradientBrush.GradientOriginProperty)); 

    Storyboard.SetTarget(centreAnimation, arrow); 
    Storyboard.SetTargetProperty(centreAnimation, new PropertyPath(RadialGradientBrush.CenterProperty)); 

    storyboard.Children.Add(originAnimation); 
    storyboard.Children.Add(centreAnimation); 
    return storyboard; 
} 

當我嘗試運行該項目,它成功地編譯和窗口加載SUCC在默認狀態下,控件處於有效狀態。然而,當DataTrigger大火的第一次,我得到以下異常:

System.InvalidOperationException was unhandled 
    Message='beginStoryboard' name cannot be found in the name scope of 'System.Windows.Style'. 
    Source=PresentationFramework 

我已經附上示例項目to demonstrate what I am trying to achieve

回答

2

看起來您需要使用Style.RegisterName註冊您的BeginStoryboard的名稱。喜歡的東西:

//... 
BeginStoryboard bs = new BeginStoryboard { Storyboard = storyboard, Name = "beginStoryboard" }; 
startTrigger.EnterActions.Add(bs); 
//... 
style.RegisterName(bs.Name, bs); 

對於動畫/故事板,您實際上試圖在AnimatedLineArrow(不是實際放射漸變)動畫放射漸變的特性。您可能需要將故事板目標設置爲RadialGradientBrush,或者暴露AnimatedLineArrow上可以進行動畫處理的其他屬性。

喜歡的東西:

public static readonly DependencyProperty AnimatedPointProperty = DependencyProperty.Register("AnimatedPoint", 
    typeof(Point), typeof(AnimatedLineArrow), new FrameworkPropertyMetadata(new Point())); 

public Point AnimatedPoint { 
    get { return (Point)this.GetValue(AnimatedLineArrow.AnimatedPointProperty); } 
    set { this.SetValue(AnimatedLineArrow.AnimatedPointProperty, value); } 
} 

private Storyboard CreateStoryboard(AnimatedLineArrow arrow) 
{ 
    Storyboard storyboard = new Storyboard(); 

    PointAnimation originAnimation = new PointAnimation(StartingPoints[StartCorner], EndingPoints[StartCorner], Duration, FillBehavior.HoldEnd); 
    Storyboard.SetTarget(originAnimation, arrow); 
    Storyboard.SetTargetProperty(originAnimation, new PropertyPath(AnimatedPointProperty)); 
    storyboard.Children.Add(originAnimation); 
    return storyboard; 
} 

然後在你的AnimatedLineArrow.xaml,你需要使用:

<RadialGradientBrush RadiusX="0.2" RadiusY="1.0" 
         Center="{Binding ElementName=animatedLineArrow, Path=StartPoint, Mode=OneWay}" 
         GradientOrigin="{Binding ElementName=animatedLineArrow, Path=AnimatedPoint, Mode=OneWay}"> 
    <RadialGradientBrush.GradientStops> 
     <GradientStop Color="{Binding ElementName=animatedLineArrow, Path=HighlightColour, Mode=OneWay, FallbackValue=Cyan}" Offset="0.0" /> 
     <GradientStop Color="{Binding ElementName=animatedLineArrow, Path=PrimaryColour, Mode=OneWay, FallbackValue=Navy}" Offset="1.0" /> 
    </RadialGradientBrush.GradientStops> 
</RadialGradientBrush> 
+0

非常感謝您的提示,@CodeNaked。它肯定會照顧DataTrigger開啓時產生的IOE。然而,動畫仍然沒有發生 - 關於爲什麼會這樣的想法? – 2011-05-03 23:11:38

+0

我已經嘗試了所有的數據觸發器事件,並且在完成設置時啓動故事板,但仍然沒有動畫。這表明問題在於我如何設置故事板及其動畫。 – 2011-05-04 06:36:27

+0

@大衛 - 我更新了我的答案。 – CodeNaked 2011-05-04 11:27:21