実はあなたはViewModel
プロパティにDoubleAnimation.ToProperty
を結合して、実際のコントロールをアニメーション化します。問題は、ToProperty
が変更されたときにアニメーションを続けることです。私の解決策は、を包むMarkupExtenstion
にこのすべてのロジックをカプセル化します。
public class AnimateBindingExtension : MarkupExtension {
static DependencyPropertyDescriptor dpd =
DependencyPropertyDescriptor.FromProperty(DoubleAnimation.ToProperty,
typeof(DoubleAnimation));
public AnimateBindingExtension(PropertyPath path) {
Path = path;
}
public bool ValidatesOnExceptions { get; set; }
public IValueConverter Converter { get; set; }
public object ConverterParamter { get; set; }
public string ElementName { get; set; }
public RelativeSource RelativeSource { get; set; }
public object Source { get; set; }
public bool ValidatesOnDataErrors { get; set; }
[ConstructorArgument("path")]
public PropertyPath Path { get; set; }
public object TargetNullValue { get; set; }
public override object ProvideValue(IServiceProvider serviceProvider) {
var valueProvider = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;
if (valueProvider == null) {
throw new Exception("could not get IProviderValueTarget service.");
}
var bindingTarget = valueProvider.TargetObject as FrameworkElement;
var bindingProperty = valueProvider.TargetProperty as DependencyProperty;
if (bindingProperty == null || bindingTarget == null) {
throw new Exception();
}
var binding = new Binding {
Path = Path,
Converter = Converter,
ConverterParameter = ConverterParamter,
ValidatesOnDataErrors = ValidatesOnDataErrors,
ValidatesOnExceptions = ValidatesOnExceptions,
TargetNullValue = TargetNullValue
};
if (ElementName != null) binding.ElementName = ElementName;
else if (RelativeSource != null) binding.RelativeSource = RelativeSource;
else if (Source != null) binding.Source = Source;
// you can add a Duration property to this class and use it here
var anim = new DoubleAnimation {
Duration = new Duration(TimeSpan.FromSeconds(0.1)),
AccelerationRatio = 0.2,
DecelerationRatio = 0.8
};
// this can be a new subclass of DoubleAnimation that
// overrides ToProperty metadata and add a property
// change callback
dpd.AddValueChanged(anim, (s, e) => bindingTarget.BeginAnimation(bindingProperty, anim));
BindingOperations.SetBinding(anim, DoubleAnimation.ToProperty, binding);
// this is because we need to catch the DataContext so add animation object
// to the visual tree by adding it to target object's resources.
bindingTarget.Resources[bindingProperty.Name] = anim;
// animation will set the value
return DependencyProperty.UnsetValue;
}
}
他のアニメーションクラスと同じことを行い、他のタイプをアニメーションできます。
私は本当にこれが私が必要とする方向であるかどうかはわかりません。ストーリーボードを実行してPreviousWidthとCurrentWidthをアニメーションのtoプロパティとfromプロパティにバインドするように命令するために、ルーテーションを使用する必要があります。これはこれを行う唯一の方法かもしれません。まだわからないDataTriggersは、動的な変更ではなく、状態スタイルの変更に対してのみ機能します。これは私がパターンから少し離れてしまう傾向があるところです。 – cjibo