【发布时间】:2016-06-16 11:39:03
【问题描述】:
我在 MVVM 中遇到了附加属性的问题。我正在构建一个 C# WPF 应用程序。
我正在使用 ClassObject 类型的自定义类填充 ObserverableCollection。从这个集合中,我正在画布上创建 ClassShapeViews。这些 ClassShapeView 需要对 ClassObject 的引用才能显示正确的信息。
要传递 ClassObject 引用,我将绑定到 XAML 中的 AttachedProperty,如下所示:
<ItemsControl ItemsSource="{Binding ClassObjectList}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas x:Name="canvas" Background="White" AllowDrop="True"
DragEnter="canvas_DragEnter"
DragOver="canvas_DragOver"
Drop="canvas_Drop"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<!-- This part doesn't work-->
<shape:ClassShapeView>
<Style TargetType="shape:ClassShapeView">
<Setter Property="shape:ClassShapeView.ClassObject" Value="{Binding}"/>
</Style>
</shape:ClassShapeView>
<Label Content="{Binding Name}"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
在 ClassShapeView 后面的代码中,我正在处理 DependencyProperty:
public partial class ClassShapeView : UserControl
{
protected ClassShapeViewModel viewModel { get { return DataContext as ClassShapeViewModel; } }
public ClassShapeView()
{
InitializeComponent();
this.DataContext = new ClassShapeViewModel();
}
public static readonly DependencyProperty ClassObjectProperty =
DependencyProperty.RegisterAttached("ClassObject", typeof(ClassObject), typeof(ClassShapeView), new PropertyMetadata(default(ClassObject)));
public static void SetClassObject(UIElement element, ClassObject value)
{
element.SetValue(ClassObjectProperty, value);
}
public static ClassObject GetClassObject(UIElement element)
{
return (ClassObject)element.GetValue(ClassObjectProperty);
}
public ClassObject MyClassObject
{
get { return viewModel.ClassObject; }
set { viewModel.ClassObject = value; }
}
}
收到 ClassObject 引用后,我想将此引用发送到带有 MyClassObject 属性的附加 ViewModel。 ClassShapeView 中的数据与 ViewModel 绑定。
我只是不知道如何将 ClassObject 引用从 CodeBehind 转换为 ViewModel。
【问题讨论】:
-
项容器(及其所有子项)的 DataContext 已自动设置为适当的数据项对象。所以将
ClassObject设置为{Binding}似乎完全是多余的。只需从 ClassShapeView 的构造函数中删除this.DataContext = new ClassShapeViewModel();即可启用继承 DataContext 并让 UserControl 直接对继承的 DataContext 中的 ClassObject 实例进行操作。 -
这是一种非常不寻常的做事方式。通常,视图模型之间的关系和连接是由视图模型本身建立的。该视图仅反映了它在那里的发现。为什么不将 ClassObject 的属性绑定到 ShapeView 的属性?无论如何,在您的 DataTemplate 中,
{Binding}是 DataContext——ClassObject。你想要{Binding RelativeSource={RelativeSource Self}}。我会直接在 ShapeView 上尝试,而不是在样式设置器中。 -
换句话说,用户控件不需要使用自己的视图模型。尤其是在它应该在继承的 DataContext 上操作的场景中使用时,它永远不应该创建自己的视图模型实例。另请参阅this answer。
-
@Clemens 所以你是说用户控件不能有它自己的 ViewModel?
-
所以新问题是?我是否使用视图模型以及如何设置对象引用以便它可以绑定到用户控件中?
标签: c# wpf xaml mvvm dependency-properties