2011-02-03 68 views
1

如何連接在控件模板中進行動畫的自定義控件屬性?在動畫中使用自定義控件屬性

我正在創建一個具有幾種狀態的自定義按鈕,並且我想在狀態更改時爲按鈕文本的顏色設置動畫。通常,文本是灰色的,並且在MouseOver上變爲黑色。

我創建了一個NormalTextBrush爲黑色文本和FadedTextBrush爲灰色文本:

<SolidColorBrush x:Key="NormalTextBrush" Color="Black" /> 
<SolidColorBrush x:Key="FadedTextBrush" Color="DarkSlateGray" /> 

到目前爲止,一切都很好。我的動畫無誤地運行。當鼠標移過按鈕時,文本從灰色變爲黑色。但是我真正想要做的是讓使用該控件的開發人員指定文本顏色。

因此,我重新定義了兩個文本畫筆作爲綁定到控件的Foreground屬性。 FadedTextBrush使用值轉換器來淡化前景色。重新定義的資源如下所示:

<SolidColorBrush x:Key="NormalTextBrush" Color="{Binding Path=Foreground, RelativeSource={RelativeSource TemplatedParent}}" /> 
<SolidColorBrush x:Key="FadedTextBrush" Color="{Binding Path=Foreground, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource ColorConverter}, ConverterParameter='1.2'}" /> 

這就是我遇到麻煩的地方。 WPF不允許綁定控件模板中的動畫。它會拋出一個異常,並顯示消息「無法凍結此Storyboard時間軸樹以供跨線程使用」。該問題記錄在here

這使我想到了我的問題:如何設置我的畫筆資源,以便它們連接到Foreground屬性,但仍然可以在控制模板中使用動畫。

任何人都可以回答這個問題,下次見到你我會給你買一瓶啤酒!謝謝你的幫助。

回答

0

你必須用可用的工具來完成。我會建議佔據相同屏幕空間的兩個文本塊,然後操作故事板中每個文本塊的不透明度。下面是如何覆蓋兩個文本塊,其中最上面的一個是在默認狀態下是透明:

<Grid> 
    <TextBlock x:Name="textBlock1" Foreground="Black" 
     Margin="{TemplateBinding Padding}" 
     VerticalAlignment="{TemplateBinding VerticalContentAlignment}" 
     HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
     SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" 
     Text="{TemplateBinding Content}"/> 
    <TextBlock x:Name="textBlock2" Foreground="Gray" 
     Margin="{TemplateBinding Padding}" 
     VerticalAlignment="{TemplateBinding VerticalContentAlignment}" 
     HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
     SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" 
     Text="{TemplateBinding Content}" Opacity="0"/> 
</Grid> 

然後建立一個視覺狀態組的可視狀態管理器來交換他們不透明度:

<VisualStateGroup x:Name="CommonStates"> 
    <VisualStateGroup.Transitions> 
     <VisualTransition GeneratedDuration="0:0:0.5"/> 
    </VisualStateGroup.Transitions> 
    <VisualState x:Name="Normal"/> 
    <VisualState x:Name="MouseOver"> 
     <Storyboard> 
      <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="textBlock1"> 
       <EasingDoubleKeyFrame KeyTime="0" Value="0"/> 
      </DoubleAnimationUsingKeyFrames> 
      <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="textBlock2"> 
       <EasingDoubleKeyFrame KeyTime="0" Value="1"/> 
      </DoubleAnimationUsingKeyFrames> 
     </Storyboard> 
    </VisualState> 
    <VisualState x:Name="Pressed"/> 
    <VisualState x:Name="Disabled"/> 
</VisualStateGroup> 

或者你可以使用你自己的故事板。重點是我們現在使用故事板操作常量值,但是您可以使用您選擇的任何方法設置每個狀態的文本塊的前景。

+0

我接受了這個回答,因爲它確實回答了我提出的問題。但我認爲有一個更簡單的解決方案 - 我將轉儲狀態更改動畫並使用樣式觸發器執行無動畫狀態更改。 – 2011-02-04 15:56:03