我遇到了同样的问题,但使用 TriggerAction 解决了它。System.Windows.Interactivity
如果您有Blend SDK,您可以使用。该dll位于
c:\Program Files\Microsoft SDKs\Expression\Blend\Silverlight\v4.0\Libraries\
System.Windows.Interactivity.dll`
然后,通过使用您以前的 xaml 代码,我可以这样设置数据模板:
<ItemsControl.ItemTemplate>
<DataTemplate>
<Ellipse Stroke="Red" Width="2" Height="2">
<ia:Interaction.Triggers>
<ia:EventTrigger EventName="Loaded">
<tr:SetCanvasPropertiesAction Left="{Binding X}" Top="{Binding Y}" />
</ia:EventTrigger>
</ia:Interaction.Triggers>
</Ellipse>
</DataTemplate>
</ItemsControl.ItemTemplate>
请注意ia:Interaction
前面提到的交互 dll 中的前缀。你加载它
xmlns:ia="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
在您的 xaml 文件的顶部。
tr 前缀用于包含我自己的类,如下所示:
using System.Windows;
using System.Windows.Controls;
using System.Windows.Interactivity;
using System.Windows.Media;
namespace Presentation.Triggers {
public class SetCanvasPropertiesAction : TriggerAction<DependencyObject> {
public static readonly DependencyProperty LeftProperty =
DependencyProperty.Register("Left", typeof(double), typeof(SetCanvasPropertiesAction), new PropertyMetadata(default(double)));
public static readonly DependencyProperty TopProperty =
DependencyProperty.Register("Top", typeof(double), typeof(SetCanvasPropertiesAction), new PropertyMetadata(default(double)));
public double Top {
get { return (double)GetValue(TopProperty); }
set { SetValue(TopProperty, value); }
}
public double Left {
get { return (double)GetValue(LeftProperty); }
set { SetValue(LeftProperty, value); }
}
protected override void Invoke(object parameter) {
UIElement presenter = (UIElement)VisualTreeHelper.GetParent(AssociatedObject);
Canvas.SetLeft(presenter, Left);
Canvas.SetTop(presenter, Top);
}
}
}
Invoke 方法需要注意两点。第一个是AssociatedObject
,它被解析为 Ellipse,因为触发器在 xaml 中嵌套在它下面。第二件事是 VisualTreeHelper,它将父级获取到椭圆。这是我们要设置画布附加属性的 ContentPresenter。
它可能看起来更复杂,但与 mvvm 中的所有其他内容一样,您可以在 xaml 中重用它,而不必到处复制和粘贴代码隐藏代码。