0
votes

I can't get command binding to work in a child view to work. Also I want to check if I do the right thing with the way I open child view. I'm stuck on this for a day now and I'm not sure whether it is the way I create child view or bind command. also I haven't done automatic child view close when selecting different option on main radiobuttons, any suggestions?

 <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();
        }
    }
}

and finally 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");
        }
    }
}

and I launch this with following:

    var mainViewModel = new MainViewModel();
    var window = new MainView();
    window.DataContext = mainViewModel;
    window.ShowDialog();
1
Have you set the ChildView.DataContext property with an instance of ChildViewModel ?Seb
Yes, I tried this: xmlns:local="clr-namespace:SimpleGui.ViewModels" <Grid> <Button Content="Run" DataContext="{Binding local.ChildViewModel}" Command="{Binding runDemoCommand}"/> </Grid>Irakli Ika

1 Answers

0
votes

A secondary window will not inherit the parent's window datacontext, so you need to set it explicitly.

So, lets modify your code a little bit:

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>