【问题标题】:How can I pass value from child window to parent window by ComboBox (WPF and MVVM)如何通过 ComboBox(WPF 和 MVVM)将值从子窗口传递到父窗口
【发布时间】:2015-01-04 04:00:44
【问题描述】:

我有一个子窗口,并且有一个 ComboBox。我想使用 WPF 和 MVVM 将子窗口的值发送到父窗口。谁能帮我怎么做??

【问题讨论】:

  • 您能帮我们说说您尝试过什么吗?

标签: wpf mvvm


【解决方案1】:

在这种情况下不要专注于 MVVM,MVVM 不是为将值从子窗口传回父窗口而设计的。

相反,如果您在视图模型中有一些代码或在生成或打开子窗口的视图后面的代码,则该代码应负责检索由子窗口确定的值并将其传播回适当的属性(此时任何绑定都会在 UI 中反映该值 - 这是应该使用 MVVM 的地方)。

您可以做的最好的事情是确保打开子窗口的代码不会直接访问子窗口上的 ComboBox,而是子窗口应将其绑定到一个属性,然后由父代码访问该属性(最好通过接口)。

如需进一步阅读,请查看Creating an MVVM friendly dialog strategy。这应该是您的首选方案,然后父代码简单地使用 Dialog Service 来显示子窗口,而 Dialog Service 负责聚合子窗口结果并将其返回给父窗口中的调用代码。

【讨论】:

    【解决方案2】:

    由于您没有提供足够的信息,因此假设子窗口是一个对话框。现在,让我们假设子窗口是一个 Child() 类,其 ViewModel 具有 Child 类中的对象,比如

    public ChildViewModel chVM { get; set; } 
    

    这个视图模型具有以下属性:

    public string ComboBoxSelectedValue { get; set; }
    

    让具有组合框的对话框的 xaml 如下所示:-

    <ComboBox Name="cbTest" SelectedItem="{Binding ComboBoxSelectedValue}">
    <ComboBoxItem>A</ComboBoxItem>
    <ComboBoxItem>B</ComboBoxItem>
    <ComboBoxItem>C</ComboBoxItem>
    </ComboBox>
    

    现在,每次在 combobnox 中选择一个值时,其视图模型中的属性,即 ComboBoxSelectedValue 都会被选择的值填充。

    您必须在父页面上处理对话框的关闭事件。让我们转到作为父页面的类 Parent():

    public partial class Parent : Page
    {
        private Child ch;
    
        public Parent()
        {
            InitializeComponent();
    
            ch= new Child();
            ch.Closed += ChildClosed;
        }
    
        public void ChildClosed(object sender, System.EventArgs e)
        {
            //even after closing of child window
            var selectedValue = ch.chVM.ComboBoxSelectedValue;
        }
    
        public void OpenChild(object sender, System.EventArgs e)
        {
            //Button event to open the child window
            ch.Show();
        }
    }
    

    如果这是您需要的,请回复。否则,请随时要求其他解决方案。这也可以在没有 mvvm 的情况下完成,但是由于您要求使用 MVVM,所以这就是解决方案。

    【讨论】:

    • 虽然这是一个选项,但它是一个糟糕的方法 - 您正在通过视图深入到视图模型的内部。父级应该只知道它创建的直接对象 - 任何更多都违反了几个 OO 和/或设计规则。如果您打开视图,可以知道这一点 - 但对视图模型及其属性做出假设是不好的。视图模型可以是任何东西——这是 MVVM 的基础之一。如果你打算这样做,那么至少接口的东西。
    【解决方案3】:

    我发现允许视图模型相互通信的最佳解决方案是通过消息传递框架,我的首选是 nuget 上可用的 MVVM light。

    您的子视图模型通过父订阅的框架发送消息。与事件处理程序没有什么不同。

    孩子...

    Messenger.Default.Send<MyMessageClass>(message);
    

    这可以在组合框中选择项绑定设置器,或命令操作方法的一部分。

    家长...

    Messenger.Default.Register<MyMessageClass>(this, OnMessage);
    

    MyMessageClass 必须扩展 BaseMessage 并且应该包含您要共享的数据的属性。父级中的 OnMessage 方法应接受此类作为参数,并使用这些值在父级中执行您需要的任何操作。

    是更好的 MVVM,因为它将逻辑排除在代码后面或视图之外,但也不会产生强耦合。如果一个视图模型发送了一条其他视图模型没有收到的消息,则什么也不会发生 - 您还可以使用消息对象而不是检查视图模型来共享数据。

    msdn here上的教程。

    【讨论】:

    • 这是一种不好的方法 - 消息传递适用于当您有多个可能处于活动或可能不处于活动状态的收件人需要通知更改时 - 例如更改的设置可能会影响多个不同的窗口。消息传递也不是 MVVM,当您收到大量可能的消息时会导致维护问题。是的,它是解耦的,但对于父/子对话场景,消息传递是非常过分的。
    • 我倾向于不同意,并将其作为基于不了解实施细节的建议的另一种选择。它适用于有零到多个收件人并正确完成的地方,不提供任何真正的维护。我承认单元测试可能会令人讨厌,但对于可扩展性和解耦,我认为它运作良好。这当然是意见,你有权获得你的意见。我要补充一点,如果查看一个真正的父子模型,其中子视图和父视图本质上是链接的,请共享同一视图模型的单个实例。
    猜你喜欢
    • 1970-01-01
    • 2010-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-13
    • 1970-01-01
    相关资源
    最近更新 更多