【问题标题】:MVVM Attached Property View ModelMVVM 附加属性视图模型
【发布时间】: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


【解决方案1】:

感谢克莱门斯,我得到了答案

“当 ItemsControl 的 ItemsSource 属性绑定到 ClassObject 实例的集合(我想是您的 ClassObjectList)时,每个项目容器(例如 ContentPresenter)的 DataContext 被设置为集合中的相应元素。这个DataContext 被继承到 ItemTemplate 中,因此 DataTemplate 中的控件(例如您的 UserControl)已经获得了正确的 ClassObject 元素作为它们的 DataContext。"

所以我的 XAML 现在看起来像这样

        <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>
                    <shape:ClassShapeView/>
                </StackPanel>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>

我的视图如下所示:

    public partial class ClassShapeView : UserControl
{
    public ClassShapeView()
    {
        InitializeComponent();     
    }
}

【讨论】:

    猜你喜欢
    • 2022-11-19
    • 2021-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多