2017-06-05 9 views
1

DurationプロパティーColorAnimationValueプロパティーをSliderのようにバインドする方法については、ここでgood explanationが見つかりました。コンバータを使用して、にDoubleの値を変換し、DurationColorAnimationに設定したBindingに変換します。ここでは、省略、それがどのように動作するかです:ControlTemplateのアニメーションの長さにデータバインディングを使用できますか?

<Window.Resources> 
    <local:DoubleToDurationConverter x:Key="DoubleToDurationConverter" /> 
</Window.Resources> 

<Slider x:Name="slider" /> 


<Button Content="Click me for an animation"> 
    <Button.Triggers> 
     <EventTrigger RoutedEvent="Button.Click"> 
      <BeginStoryboard> 
       <Storyboard> 
        <ColorAnimation To="Green" 
         Storyboard.TargetProperty="(Button.Background).(SolidColorBrush.Color)" 
         FillBehavior="Stop" 
         Duration="{Binding ElementName=slider, 
              Path=Value, 
              Mode=OneWay, 
              Converter={StaticResource DoubleToDurationConverter}}" /> 
       </Storyboard> 
      </BeginStoryboard> 
     </EventTrigger> 
    </Button.Triggers> 
</Button> 

私はそれを試してみました、それは私のためにうまく働きました。しかし、私がしたいのはDurationを私のカスタムコントロールに追加したFadeTimeという依存関係のプロパティにバインドすることです。だから、そのコントロールのControlTemplate私が持っている中で、この:

<ControlTemplate.Triggers> 
    <Trigger Property="IsLit" Value="true"> 
     <Trigger.EnterActions> 
      <BeginStoryboard> 
       <Storyboard> 
        <DoubleAnimation Storyboard.TargetName="glow" 
            Storyboard.TargetProperty="Opacity" 
            To="1" 
            Duration="{Binding FadeTime, Mode=OneWay, 
               RelativeSource={RelativeSource TemplatedParent}}"/> 
       </Storyboard> 
      </BeginStoryboard> 
     </Trigger.EnterActions> 
    </Trigger> 
</ControlTemplate.Triggers> 

これはコンパイルが、私は実行時にエラーメッセージを与える:

と、InvalidOperationException:スレッド間での使用のために、このストーリーボードのタイムラインツリー を凍結することはできませんが。

は、どのように私はカスタムコントロールのControlTemplateで依存変数に私のDoubleAnimationDurationをバインドすることができますか?

ありがとうございます!

UPDATE

データ・バインディングは、実際に私が何をしたいの売上総やり過ぎです。実際のデータバインディングは、プロパティの値が実行時に変更されるようにします。私が本当に欲しいのは、ControlTemplateを編集することなく、デザイン時にDoubleAnimationDurationをカスタムコントロールを使って設定できる開発者のための方法です。開発者が選択した値が実行時に決して変更されない場合は、大丈夫です。

答えて

1

代わりにあなたのXAMLマークアップでアニメーションを定義する、あなたはそれを定義することができプログラミングによってのIsLitプロパティを参照してください。

コントロールのコンシューマがアニメーションの期間を指定できるようにする別のプロパティを定義するだけで済みます。

次はあなたの例です。

コントロール:

public class MyCustomControl : Control 
{ 
    private UIElement glow; 

    public static readonly DependencyProperty DurationProperty = 
     DependencyProperty.Register("Duration", typeof(TimeSpan), 
     typeof(MyCustomControl), new PropertyMetadata(TimeSpan.FromSeconds(1))); 

    public TimeSpan Duration 
    { 
     get { return (TimeSpan)GetValue(DurationProperty); } 
     set { SetValue(DurationProperty, value); } 
    } 

    public static readonly DependencyProperty IsLitProperty = 
     DependencyProperty.Register("IsLit", typeof(bool), 
     typeof(MyCustomControl), new PropertyMetadata(false, new PropertyChangedCallback(OnIsLitChanged))); 

    public bool IsLit 
    { 
     get { return (bool)GetValue(IsLitProperty); } 
     set { SetValue(IsLitProperty, value); } 
    } 

    public override void OnApplyTemplate() 
    { 
     base.OnApplyTemplate(); 
     glow = Template.FindName("glow", this) as UIElement; 
     if (glow != null && IsLit) 
      Animate(glow); 

    } 

    private static void OnIsLitChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     bool newValue = (bool)e.NewValue; 
     if(newValue) 
     { 
      MyCustomControl c = d as MyCustomControl; 
      if(c != null && c.glow != null) 
      { 
       c.Animate(c.glow); 
      } 
     } 
    } 

    private void Animate(UIElement glow) 
    { 
     DoubleAnimation animation = new DoubleAnimation(); 
     animation.To = 1; 
     animation.Duration = Duration; 
     glow.BeginAnimation(OpacityProperty, animation); 
    } 
} 

テンプレート:

<ControlTemplate x:Key="ct" TargetType="local:MyCustomControl"> 
    <Border x:Name="glow" Width="100" Height="100" Background="Red" Opacity="0.1"> 
    </Border> 
</ControlTemplate> 

用途:

<local:MyCustomControl Template="{StaticResource ct}" Duration="0:0:5" IsLit="True" /> 
+0

これはよく見えます。私はそれを試してみます! –

+0

@ mm8で完璧に作業しました!残念ながら、これを行うための(明らかに)純粋なXAMLの方法はありませんが、おそらく "XAML、XAMLだけ"という絶対的なものではないはずです。大きな助けをありがとう! –

1

基本的に、コントロールテンプレートのストーリーボード内で通常のバインディングを使用することはできません。

(1)StaticResourceを使用してください:デベロッパーの方が変更しやすいコントロールテンプレートの外側にデュレーションオブジェクトを配置してください。ただし、DynamicResourceはこの場所では機能しないため、コントロールテンプレートに静的にアクセスできる場所にする必要があります。

<Duration x:Key="MyCustomDuration">0:0:1</Duration> 
... then later 
Duration="{StaticResource MyCustomDuration}" 

(2)x:Staticとフィールドの背後にある静的コードを使用します。

public static class SettingsClass 
{ 
    public static Duration MyCustomDuration = new Duration(new TimeSpan(0, 0, 1)); 
} 

と使用:

Duration="{x:Static local:SettingsClass.MyCustomDuration}" 
+0

ありがとう!どちらも動作しますが、開発者がカスタムコントロールのソースコードを変更する必要があるか、コントロールの「ControlTemplate」のコピーを編集する必要があります。これらのアプローチに本質的に間違ったものは何もありませんが、私はもう少し簡潔なものを探しています。 –

関連する問題