【问题标题】:How to save data from a DetailView bound to a ViewModel if the repository is a no-go in a viewmodel?如果存储库在视图模型中不可用,如何从绑定到视图模型的 DetailView 中保存数据?
【发布时间】:2011-04-13 10:35:37
【问题描述】:

我们 mvvm 爱好者都知道 Josh Smith mvvm 示例,以及他如何通过将存储库对象注入 customerViewModel 的构造函数来在详细客户视图中保存客户。

但是视图模型不应该知道存储库。它只是一个视图模型,没有什么必须意识到持久性等......

如果在代码隐藏中设置了我的 Action 委托 SaveDocumentDelegate,我如何在 DocumentViewModel 上注册它?实际上,我应该在 DocumentController 中订阅委托,但是如何在 DocumentController 中实例化 DocumentView 并将其设置为 Datacontext 而不是在代码隐藏中执行此操作。我唯一想到的是在窗口中使用内容控件并将其绑定到 viewModel 的类型并使用 Document UserControl 对其进行数据模板,如下所示:

<UserControl.Resources>

        <DataTemplate DataType="{x:Type ViewModel:DocumentViewModel}">
            <View:DocumentDetailView/>
        </DataTemplate>

    </UserControl.Resources>

<ContentControl Content="{Binding MyDocumentViewModel}" />

但我不想使用控件来解决我的架构问题...

xaml:(查看第一种方法)

public partial class DocumentDetailView : UserControl
    {
        public DocumentDetailView()
        {
            InitializeComponent();

            this.DataContext = new DocumentViewModel(new Document());
        }
    }

DocumentViewModel:

 public class DocumentViewModel : ViewModelBase
    {
        private Document _document;
        private RelayCommand _saveDocumentCommand;
        private Action<Document> SaveDocumentDelegate;

        public DocumentViewModel(Document document)
        {
            _document = document;
        }

        public RelayCommand SaveDocumentCommand
        {
            get { return _saveDocumentCommand ?? (_saveDocumentCommand = new RelayCommand(() => SaveDocument())); }
        }

        private void SaveDocument()
        {
            SaveDocumentDelegate(_document);
        }        

        public int Id
        {
            get { return _document.Id; }
            set
            {
                if (_document.Id == value)
                    return;

                _document.Id = value;
                this.RaisePropertyChanged("Id");
            }
        }

        public string Name
        {
            get { return _document.Name; }
            set
            {
                if (_document.Name == value)
                    return;

                _document.Name = value;
                this.RaisePropertyChanged("Name");
            }
        }

        public string Tags
        {
            get { return _document.Tags; }
            set
            {
                if (_document.Tags == value)
                    return;

                _document.Tags = value;
                this.RaisePropertyChanged("Tags");
            }
        }
    }

更新

public class DocumentController
    {
        public DocumentController()
        {    
            var win2 = new Window2();
            var doc =  new DocumentViewModel(new DocumentPage());
            doc.AddDocumentDelegate += new Action<Document>(OnAddDocument);
            win2.DataContext = doc;
            wind2.ShowDialog();
        }

        private void OnAddDocument(Document doc)
        {
            _repository.AddDocument(doc);
        }
    }

你觉得这个想法怎么样?

【问题讨论】:

  • 当然 Window 是由 IDialog/WindowService 获取的 :)

标签: wpf mvvm view save viewmodel


【解决方案1】:

但是视图模型不应该知道 存储库。它只是一个模型 没有什么必须意识到的 持久性等...

viewmodel 将模型和视图连接在一起;它正是控制持久性的东西,尽管它不处理持久性

我们通过使用服务将其与其他问题解耦。

避免将持久性问题添加到视图模型的一种方法是将这些问题抽象到存储库接口中,以便我们可以将其作为依赖项注入。通过这种方式,我们可以委托视图模型中的持久性工作,通常是为了响应用户与视图的交互。

【讨论】:

  • 当我听从你的建议时,我应该将 IRepository 注入 ViewModels 构造函数吗?那正是 Josh smith 没有做任何接口,他只是使用类型为 Repository 而不是 IRepository 的对象。
  • 我用示例代码更新了 init 线程,请查看 Jay!
  • @Lisa 您可以使用类(实现)或基类/接口(抽象)。使用抽象允许您替换不同的实现,这可能是替代方案、适配器或用于测试的存根/模拟。至于您的更新,这似乎仅适用于顶级窗口。以我的经验,通常会有带有自己的视图模型的“子控件”,但这里可能只有一个处理文档的窗口,而不需要任何其他视图模型。
  • 那么将 IDocumentRepository 注入 DocumentViewModels 构造函数对您来说可以吗?
  • hm 是的,我认为您可能是对的,可能您是:P 它就像 MVP 模式,演示者注入了 IView...谢谢!啊还有一个问题,最重要的一个问题...当我在代码隐藏中将 DocumentViewModel 设置为 UserControl 的 Datacontext 时,如何注入 IDocumentRepository?
猜你喜欢
  • 2021-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-18
  • 1970-01-01
  • 2013-09-25
  • 2013-05-16
相关资源
最近更新 更多