研究員WPF用戶,WPF行爲+故事板動畫= AssociatedObject的是空
我目前正在試圖總結我的周圍與WPF混合行爲問題的頭。我發現了一個我想在WPF應用程序中使用的行爲,但代碼最初是爲Silverlight編寫的(http://www.sharpgis.net/post/2009/08/11/Silverlight-Behaviors-Triggers-and-Actions.aspx)。
我的問題是,當動畫開始和依賴屬性OffsetMediatorProperty
變化,我進入方法OnOffsetMediatorPropertyChanged
,該AssociatedObject
是null
。另外,它也看起來像所有的字段是null
。
我使用的行爲:
public class MouseScrollViewer : Behavior<ScrollViewer>
{
double target = 0;
int direction = 0;
private Storyboard storyboard;
private DoubleAnimation animation;
protected override void OnAttached()
{
base.OnAttached();
CreateStoryBoard();
AssociatedObject.PreviewMouseWheel += AssociatedObject_MouseWheel;
}
protected override void OnDetaching()
{
AssociatedObject.PreviewMouseWheel -= AssociatedObject_MouseWheel;
storyboard = null;
base.OnDetaching();
}
private void AssociatedObject_MouseWheel(object sender, MouseWheelEventArgs e)
{
if (Animate(-Math.Sign(e.Delta) * ScrollAmount))
{
e.Handled = true;
}
}
private bool Animate(double offset)
{
storyboard.Pause();
if (Math.Sign(offset) != direction)
{
target = AssociatedObject.VerticalOffset;
direction = Math.Sign(offset);
}
target += offset;
target = Math.Max(Math.Min(target, AssociatedObject.ScrollableHeight), 0);
animation.To = target;
animation.From = AssociatedObject.VerticalOffset;
if (animation.From != animation.To)
{
storyboard.Begin();
return true;
}
return false;
}
private void CreateStoryBoard()
{
storyboard = new Storyboard();
animation = new DoubleAnimation
{
Duration = TimeSpan.FromSeconds(.5),
EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut }
};
Storyboard.SetTarget(animation, this);
Storyboard.SetTargetProperty(animation, new PropertyPath(OffsetMediatorProperty));
storyboard.Children.Add(animation);
storyboard.Completed += (s, e) => { direction = 0; };
}
internal double OffsetMediator
{
get { return (double)GetValue(OffsetMediatorProperty); }
set { SetValue(OffsetMediatorProperty, value); }
}
internal static readonly DependencyProperty OffsetMediatorProperty =
DependencyProperty.Register("OffsetMediator", typeof(double), typeof(MouseScrollViewer), new PropertyMetadata(0.0, OnOffsetMediatorPropertyChanged));
private static void OnOffsetMediatorPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
MouseScrollViewer msv = d as MouseScrollViewer;
if (msv != null && msv.AssociatedObject != null)
{
msv.AssociatedObject.ScrollToVerticalOffset((double)e.NewValue);
}
}
public double ScrollAmount
{
get { return (double)GetValue(ScrollAmountProperty); }
set { SetValue(ScrollAmountProperty, value); }
}
public static readonly DependencyProperty ScrollAmountProperty =
DependencyProperty.Register("ScrollAmount", typeof(double), typeof(MouseScrollViewer), new PropertyMetadata(50.0));
}
用法:
<ScrollViewer>
<i:Interaction.Behaviors>
<local:MouseScrollViewer x:Name="ScrollViewer" />
</i:Interaction.Behaviors>
<ItemsControl ItemsSource="{Binding}"
FontSize="32">
</ItemsControl>
</ScrollViewer>
它看起來像行爲Silverlight的演示工作,而不是在一個WPF應用程序。我真的希望你們中的一些能夠向我解釋爲什麼會發生這種情況,希望能幫助我理清這個問題。
戴上斷點法'OnAttached()',看看是否曾經被調用。如果是,AsscoiatedObject在這種情況下的價值是什麼。並從您設置DP OffsetMediator值的位置開始? –
是的,確實調用了'OnAttached()'方法。關聯對象的值是我的滾動查看器的實例。關於DP,這是通過在Storyboard.SetTargetProperty(animation,new PropertyPath(OffsetMediatorProperty))語句中的'CreateStoryBoard()'方法中設置的Storyboard動畫設置的。 –
我應該補充說,如果我直接設置DP(例如在Animate()方法中),則AssociatedObject不是null。所以我懷疑問題與通過動畫設置的方式有關。 –