子视图中的 MVVM light 命令绑定损坏

MVVM light Command binding in childview broken

我无法让命令绑定在子视图中工作。我还想检查我打开子视图的方式是否正确。我已经坚持了一天了,我不确定这是我创建子视图还是绑定命令的方式。我还没有在主单选按钮上选择不同的选项时自动关闭子视图,有什么建议吗?

 <Window x:Class="SimpleGui.Views.MainView"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            mc:Ignorable="d"
            Title="Main" Height="450" Width="800">
        <Grid Margin="10">
            <DockPanel Grid.Column="2">
                <Grid Height="403" VerticalAlignment="Bottom">
                    <Grid.RowDefinitions>
                    </Grid.RowDefinitions>
                    <StackPanel Margin="0,30,0,0">
                        <RadioButton Content="ChildView" Command="{Binding ShowChildCommand, Mode=TwoWay}"/>
                        <RadioButton Content="SomeOther"/>
                    </StackPanel>
                </Grid>
            </DockPanel>
        </Grid>
    </Window>

mainView.cs

using GalaSoft.MvvmLight.Messaging;
using System.Windows;

namespace SimpleGui.Views
{
    public partial class MainView : Window
    {
        private static ChildView _childView = null;
        public MainView()
        {
            InitializeComponent();
            Messenger.Default.Register<NotificationMessage>(this, NotificationMessageReceived);
        }
        private void NotificationMessageReceived(NotificationMessage msg)
        {
            if (msg.Notification == "ShowChildView")
            {
                if (_childView == null)
                {
                    _childView= new ChildView();
                    _childView.Owner = Window.GetWindow(this);
                    _childView.Show();
                }
                _childView.Closed += _childView_Closed;
            }
        }
        private void _childView_Closed(object sender, System.EventArgs e)
        {
            _childView = null;
        }
    }
}

MainViewModel.cs

using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.CommandWpf;
using GalaSoft.MvvmLight.Messaging;
using System.Windows.Input;

namespace SimpleGui.ViewModels
{
    public class MainViewModel: ViewModelBase
    {
        private ChildViewModel childViewModel;
        public ICommand ShowChildCommand { get; set; } = new RelayCommand(ShowChild);
        private static void ShowChild() => Messenger.Default.Send<NotificationMessage>(new NotificationMessage("ShowChildView"));
        public MainViewModel()
        {
            childViewModel = new ChildViewModel(this);
        }
    }
}

ChildView.xaml

<Window x:Class="SimpleGui.Views.ChildView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:SimpleGui.ViewModels"
        mc:Ignorable="d" Height="100" Width="200">
    <Grid>
        <Button 
            Content="Run" 
            DataContext="{Binding local.ChildViewModel}"
            Command="{Binding runDemoCommand}"/>
    </Grid>
</Window>

ChildView.cs

namespace SimpleGui.Views
{
    public partial class ChildView : Window
    {
        public ChildView()
        {
            InitializeComponent();
        }
    }
}

最后是 childViewModel

namespace SimpleGui.ViewModels
{
    public class ChildViewModel : ViewModelBase
    {
        public ICommand runDemoCommand { get; private set; }
        
        public ChildViewModel(MainViewModel main)
        {
            runDemoCommand  = new RelayCommand(runDemo);

        }
        public  void runDemo()
        {
            MessageBox.Show("command running");
        }
    }
}

我用以下内容启动它:

    var mainViewModel = new MainViewModel();
    var window = new MainView();
    window.DataContext = mainViewModel;
    window.ShowDialog();

辅助 window 不会继承父 window 数据上下文,因此您需要明确设置它。

那么,让我们稍微修改一下您的代码:

mainView.cs

using GalaSoft.MvvmLight.Messaging;
using System.Windows;

namespace SimpleGui.Views
{
    public partial class MainView : Window
    {
        private static ChildView _childView = null;
        public MainView()
        {
            InitializeComponent();
            Messenger.Default.Register<NotificationMessage>(this, NotificationMessageReceived);
        }

        private void NotificationMessageReceived(NotificationMessage msg)
        {
            if (msg.Notification == "ShowChildView")
            {
                if (_childView == null)
                {
                    _childView = new ChildView();
                    // Lets set the child view datacontext here
                    _childView.DataContext = new ChildViewModel ();
                    _childView.Owner = Window.GetWindow(this);
                    _childView.Show();
                }
                _childView.Closed += _childView_Closed;
            }
        }

        private void _childView_Closed(object sender, System.EventArgs e)
        {
            _childView = null;
        }
    }
}

mainViewModel.cs

using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.CommandWpf;
using GalaSoft.MvvmLight.Messaging;
using System.Windows.Input;

namespace SimpleGui.ViewModels
{
    public class MainViewModel: ViewModelBase
    {
        public ICommand ShowChildCommand { get; set; } = new RelayCommand(ShowChild);
        private static void ShowChild() => Messenger.Default.Send<NotificationMessage>(new NotificationMessage("ShowChildView"));
        public MainViewModel()
        {

        }
    }
}

ChildView.Xaml

<Window x:Class="SimpleGui.Views.ChildView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:SimpleGui.ViewModels"
        mc:Ignorable="d" Height="100" Width="200">
    <Grid>
        <!-- Now that the window has its own datacontext, it should be able to bind the command correctly -->
        <Button Content ="Run" 
                Command="{Binding runDemoCommand}"/>
    </Grid>
</Window>