在 MVVM 中的窗口之间传递 DataContext

Posted

技术标签:

【中文标题】在 MVVM 中的窗口之间传递 DataContext【英文标题】:Passing DataContext between windows in MVVM 【发布时间】:2011-03-11 21:51:16 【问题描述】:

在主窗口上点击我有

AddNoticeAboutWrongCity addNoticeAboutWrongCity = new AddNoticeAboutWrongCity();
addNoticeAboutWrongCity.DataContext = ((VerificationViewModule)this.DataContext).WrongCityNotice;
addNoticeAboutWrongCity.ShowDialog();

在弹出窗口有很多文本框和两个按钮

删除对象:

this.DataContext = null;

第二个选项“保存编辑的通知”不可用,因为主窗口上的用户情感数据上下文的每次更改,这是设计部门的要求:)

我不知道为什么第一个选项(它的“实施”不起作用。

第二个解释:

在 ParentWindow 我有通知列表,我可以单击 EditSelectedNotice。

在 EditNoticeWindow 我可以编辑通知或删除通知。

Editinig 有效(关闭 EditNoticeWindow 后,我在 ParentWindow 上看到更改的通知),但删除没有(通知仍在收集中 - 在控件和 this.DataContext 中)

我的视图模型:

class VerificationViewModule
    
        public ObservableCollection<ReporterNotice> ReporterNotices  get; set; 

        public ReporterNotice OtherNotice
        
            get
            
                return ReporterNotices.Where(n => n.Type == ReporterNoticeType.Other).FirstOrDefault();
            
        
        public ReporterNotice DuplicateNotice
        
            get
            
                return ReporterNotices.Where(n => n.Type == ReporterNoticeType.Duplicate).FirstOrDefault();
            
        
        public ReporterNotice WrongCityNotice
        
            get
            
                return ReporterNotices.Where(n => n.Type == ReporterNoticeType.WrongCity).FirstOrDefault();
            
            set  if(value==null)
            
                ReporterNotices.Remove(ReporterNotices.Where(n => n.Type == ReporterNoticeType.WrongCity).First());
            
            else
            
                if (ReporterNotices.Where(n => n.Type == ReporterNoticeType.WrongCity).FirstOrDefault()==null)//there is always only max one instance of this type of notice
                
                    ReporterNotices.Add(value);
                
                else
                
                    var c = ReporterNotices.Where(n => n.Type == ReporterNoticeType.WrongCity).First();
                    c = value;

                
            
        

         public VerificationViewModule()
        
            ObservableCollection<ReporterNotice> loadedReporterNotices = new ObservableCollection<ReporterNotice>();
            loadedReporterNotices.Add(new ReporterNotice()  Content = "Dublic", Type = ReporterNoticeType.WrongCity );
            loadedReporterNotices.Add(new ReporterNotice()  Content = "Hilton", Type = ReporterNoticeType.Duplicate );
            loadedReporterNotices.Add(new ReporterNotice()  Content = "Another notice", Type = ReporterNoticeType.Other );
            ReporterNotices = loadedReporterNotices;
        


    

【问题讨论】:

抱歉,我不太确定你想做什么,什么不起作用,你能详细说明一下吗? 在 ParentWindow 我有通知列表,我可以单击 EditSelectedNotice。在 EditNoticeWindow 我可以编辑通知或删除通知。编辑有效,但删除无效。 【参考方案1】:

您可以尝试以下方法。实现中介以显示窗口,并确保您对主窗口和编辑窗口的 DataContext 使用视图模型。告诉主视图模型对象正在被删除是很重要的。这是通过回调并通过 EditNoticeViewModel 上的命令路由来完成的

    //This viewmodel is on the main windows datacontext
public class ParentViewModel

    private readonly IWindowMediator _mediator;
    public ParentViewModel(IWindowMediator mediator)
    
        _mediator = mediator;
    

    public ObservableCollection<Notice> Notices  get; private set;  //bound to list in xaml

    public void OpenNotice(Notice notice)
    
        //open the window using the Mediator pattern rather than a new window directly

        _mediator.Open(new EditNoticeViewModel(notice, DeleteNotice));
    

    private void DeleteNotice(Notice notice)
    
        //This will remove it from the main window list
        Notices.Remove(notice);
    


//view model for EditNoticeWindow
public class EditNoticeViewModel

    public EditNoticeViewModel(Action<Notice> deleteCallback, Notice notice)
    
        Model = notice;

        DeleteCommand = new DelegateCommand((a) => deleteCallback(Model));
    

    //Bind in xaml to the Command of a button
    DelegateCommand DeleteCommand  get; private set; 

    //bound to the controls in the xaml.
    public Notice Model  get; private set; 


//This is a basic interface, you can elaborate as needed
//but it handles the opening of windows. Attach the view model
//to the data context of the window.
public interface IWindowMediator

    void Open<T>(T viewModel);

根据实现,您可能希望在按下删除按钮时关闭视图。您可以通过实现类似 here 中描述的关于 WorkspaceViewModel 的方法来做到这一点

【讨论】:

【参考方案2】:

为什么不将 WrongCityNotice 包装在实现 IReporterNotice 并引用父视图模型和 Delete 方法的视图模型中:

public void Delete()  _parentvm.Delete(_wrongCityNotice); 

您可以将此包装器用作 DataContext。

【讨论】:

【参考方案3】:

您正试图破坏 DataContext。 C# 不能那样工作。将对象引用设置为 null 不会删除该对象,它只会删除对它的引用。 (当不再引用一个对象时,它会被垃圾收集,但你不能直接销毁一个对象)。

DataContext = null 仅表示您的 DataContext 在本地不再指向任何对象。主视图模型仍然有一个参考,但是那里没有任何变化。您必须要求主视图模型从其集合中删除通知(最好通过回调方法 (Action),这样您就不必了解父视图模型)。

【讨论】:

以上是关于在 MVVM 中的窗口之间传递 DataContext的主要内容,如果未能解决你的问题,请参考以下文章

使用mvvm在xamarin表单中的视图之间传递数据

从Caliburn.Micro,WPF,MVVM中的另一个窗口获取信息

如何使用 MVVM 将 UserControl 从插件传递到我的主窗口?

我们一起写框架MVVM的WPF框架之绑定

如何在pyqt5中的两个窗口之间传递参数?

wpf mvvm ViewModel如何关闭view窗口