c# - 在不直接访问模型层的情况下从 View 访问模型类

标签 c# wpf mvvm

我需要在我的一个 Model 类型的用户控件中创建一个 Property,但我认为我必须防止直接访问 来自 View Layer 的 >Model Layer

我有一个模型 View 模型,它提供了我的模型对象的集合...

  • SetOfA_UserControl
  • SetOfA_ViewModel
  • A_Model

我的用户控件中需要这样的属性:

public A_Model SelectedA { get; set; }

一种方法是像下面的代码一样创建一个新的View Model 并在我的User Control 中使用它:

// ------------ View Model Layer ------------

public class SingleA_ViewModel: ModelA
{
}

// --------------- View Layer ---------------

public SingleA_ViewModel SelectedA { get; set; }

但我正试图阻止一个新的空 View 模型类继承上述模型。正确吗?

对于防止直接访问Model 层 并在我的User Control 中创建Property,您有什么建议???


编辑 1:

我有 3 个项目:

  • 查看项目
  • 查看模型项目
  • 模型项目

我想知道我是否可以阻止在 View project 中引用 Model project ....

我的 View 模型中也有一个 SelectedA 属性,我将我的逻辑放在 View model class 中,它在我的 View 中运行良好但是 我的 UserControl 中也有一个 SelectedA 属性,我将它绑定(bind)到我的 ViewModel 类中的 SelectedA 属性。 .. 但我需要直接访问 UserControl 中的 Model 来定义此属性!

当我从 View 直接访问 Model 时,我的代码是这样的:

// ------------ Model Layer ------------
public class AModel
{
}

// ------------ View Model Layer ------------
public class SetOfA_ViewModel: INotifyPropertyChanged
{
    public AModel SelectedA { get; set; }

    public ObservableCollection<AModel> Items
    {
        get { return _items; }
        set
        {
            _items = value;
            OnPropertyChanged("Items");
        }
    }

    // Other Logic codes to fill and keep SelectedA value and....
}



// --------------- View Layer ---------------
public partial class MyUserControl : UserControl
{
    public AModel SelectedA { 
    get { return (AModel)GetValue(SelectedAProperty); }
        set
        {
            var oldValue = (AModel)GetValue(SelectedAProperty);
            if (oldValue != value) SetValue(SelectedAProperty, value);
        }
    }

    public static readonly DependencyProperty SelectedAProperty =
        DependencyProperty.Register(
            "SelectedA",
            typeof(AModel),
            typeof(MyUserControl),
            new PropertyMetadata(OnSelectedAValueChanged));

    public MyUserControl ()
    {
        InitializeComponent();

        const string NAME_OF_PROPERTY_IN_VM = "SelectedA";
        var binding = new Binding(NAME_OF_PROPERTY_IN_VM) { Mode = BindingMode.TwoWay };
        this.SetBinding(SelectedAProperty, binding);
    }

    private static void OnSelectedAValueChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
    {
        //------
    }  
}

上述方法对我来说效果很好,我现在使用它但是我正在尝试删除我的 View 中对Model Project的任何直接访问和引用项目 那么我如何在我的用户控件中实现AModelSelectedA 依赖属性?

有些 friend 说可以直接从view project访问model project。我想知道正确的方法 可能的方法...!


编辑2

当我将 SelectedA 项保留在我的用户控件中时,然后像这样在我的窗口中使用它:

<userControls:MyUserControl x:Name="MyUserControl1"/>

<Label Content="{Binding ElementName=MyUserControl1, Path=SelectedA.Title}" />

编辑3

为什么我要阻止从 ViewModel 直接访问 Model?

我搜索了 MVVM 图,但没有找到从 View 到模型的直接访问。所有的图表都说:

enter image description here

.......... enter image description here

现在我们可以直接从 View 访问模型了吗?

  • 为什么有很多样例可以在网页端直接访问模型?

  • 为什么有人说你可以做到这一点?

  • 如果我们可以这样做并且直接访问模型是一个正确的实现,为什么上图中的 View 和模型之间没有任何关系???

最佳答案

View 模型不是模型,因此不应派生。

如果您决定将 View 耦合到模型,则通常由外部源指示的模型中的任何更改都可能会影响使用它的 View 。

当为每个 View 使用 View 模型时,某些 View 可能根本不会受到更改的影响,并且可以通过调整 View 或在 View 模型中编写代码来修复受影响的 View 。

是的,在两者之间添加一个额外的层是额外的工作,但它也带有从 View 到模型再返回的明确过渡点。经过几次增量后,它可能是值得的。

额外的层还为命令和验证以及查看特定属性提供了一个很好的扩展点。

如果您决定将模型公开为 View 模型的属性,那么向模型添加 View 特定的属性和命令会变得非常诱人。它们会迅速污染模型,使模型难以重复使用或再生。

没有法律,也没有警察。考虑我的论点并选择一个选项。尝试开放以稍后更改您的设计。现在看起来容易的事情以后可能会变得困难。我们不知道会发生什么;敏捷/灵活。根据我的经验,我发现对于存在多个版本的应用程序,在模型和 View 模型之间进行清晰的分离会更有效,但对于短期应用程序来说,这可能太多了。

在实现 MVVM 模式时,我始终确保模型不知道或假设有关 View 模型的任何信息,并且 View 模型不知道或假设有关 View 的任何信息。 View 模型是中间的人;它知道从哪里获取模型的实例以及将模型的更改发送到哪里。很多次我使用一个或多个知道如何获取或保存模型实例的存储库,因此 View 模型只需要知道存储库。存储库可以处理或委派其他功能,例如跨 View 模型实例的缓存。

一般来说,我为每个 View 创建一个 View 模型,并将 View 模型的一个实例分配给 View 的数据上下文。所有绑定(bind)路径(对于属性和命令)都是相对于该 View 模型的。

有时我通过向主视图模型添加属性来嵌套 View 模型,这些属性本身就是 View 模型。

关于c# - 在不直接访问模型层的情况下从 View 访问模型类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30531554/

相关文章:

c# - EF 6.0 中缺少 DbSet<entity>.Load() 函数

WPF - 在 ViewModel 中处理 ApplicationCommand

c# - 如何检查内容文件是否存在?

c# - 从 C# 中的同一个流中读取多次

c# - 如何在 C#/WPF 中以编程方式访问 Windows Media Player 库?

WPF 如何将右侧的按钮与 x 个按钮对齐

c# - 如何制作一个wpf倒数计时器?

wpf - View 和 View 模型变得太大

c# - WPF 绑定(bind) ListView ItemContainerStyle 的背景

c# - Hangfire:打开的连接太多