如何执行不同类中的命令并绑定到不同窗口中的按钮? [英] How to execute command which is in different class and bind to button in different window?

查看:102
本文介绍了如何执行不同类中的命令并绑定到不同窗口中的按钮?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是WPF新手并且正在开发WPF应用程序。我用一些样本构建了导航系统。我在主窗口上有按钮绑定到NavigationViewModel



I am new to WPF and working on a WPF app. I have build navigation system using looking at some sample. I have buttons on main window which bind to NavigationViewModel

<Button Content="Items List" Command="{Binding ItemsListCmd}"/>
<Button Content="Items" Command="{Binding ItemsEditCmd}"/>





在MainWinodw.xaml.cs



In MainWinodw.xaml.cs

public MainWindow()
{
    InitializeComponent();
    this.DataContext = new NavigationViewModel();
}



在MainWindow.xaml我有以下绑定



< ContentControl x:Name =PagesDockPanel.Dock =RightContent ={Binding SelectedViewModel}/>



这是具有ItemsListCmd和ItemsEditCmd命令的NavigationViewModel类。




In MainWindow.xaml I have bindings as below

<ContentControl x:Name="Pages" DockPanel.Dock="Right" Content="{Binding SelectedViewModel}"/>

Here is the NavigationViewModel class having ItemsListCmd and ItemsEditCmd commands.

namespace CC
{
	class NavigationViewModel : INotifyPropertyChanged
	{
		public event PropertyChangedEventHandler PropertyChanged;

		public ICommand ItemsListCmd { get; set; }
		public ICommand ItemsEditCmd { get; set; }

		private object selectedViewModel;

		public object SelectedViewModel
		{
			get {
				return selectedViewModel;
			}
			set {
				selectedViewModel = value;
				OnPropertyChanged("SelectedViewModel");
			}
		}

		public NavigationViewModel()
		{
			ItemsListCmd = new BaseCommand(OpenItemsList);
			ItemsEditCmd = new BaseCommand(OpenItemsEdit);
		}

		private void OpenItemsList(object obj)
		{
			SelectedViewModel = new ItemsListView();
		}

		private void OpenItemsEdit(object obj)
		{
			SelectedViewModel = new ItemsEditViewModel();
		}

		private void OnPropertyChanged(string propName)
		{
			if (PropertyChanged != null)
			{
				PropertyChanged(this, new PropertyChangedEventArgs(propName));
			}
		}
	}
}



我想知道如何从后面的代码中执行ItemsListCmd或ItemsEditCmd命令在某些自定义事件/操作上,例如当用户点击取消按钮或任何其他View / ViewModel时?



我尝试过:



我试图调用NavigationViewModel类但因为它被用作绑定所以不能直接访问该类。

我也是试图谷歌寻找解决方案,但找不到任何东西。


I want to know how can I execute ItemsListCmd or ItemsEditCmd commands from code behind on some custom event/action, like when user clicks on cancel button or in any other View/ViewModel?

What I have tried:

I tried to calling "NavigationViewModel" class but as that is used as Binding so not getting direct access to that class.
I also tried to google for the solution but couldn't find anything.

推荐答案

看看 MVVM Light Toolkit [ ^ ] - 此库简化了一些MVVM概念包括命令。



例如,我使用Frame控件来托管我的两个测试导航视图:

Have a look at MVVM Light Toolkit[^] - This library simplifies a number of MVVM concepts including commands.

For Example, I am using a Frame control to host my two test navigation views:
<Window 

    x:Class="WpfApp2.MainWindow"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"



    mc:Ignorable="d"

    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"



    xmlns:local="clr-namespace:WpfApp2"



    Title="WPF Navigation Example" Height="350" Width="525">

    <Window.Resources>
        <Style x:Key="FrameStyle1" TargetType="{x:Type Frame}">
            <Setter Property="BorderThickness" Value="0" />
            <Setter Property="NavigationUIVisibility" Value="Hidden" />
            <Setter Property="Margin" Value="0" />
            <Setter Property="SnapsToDevicePixels" Value="True" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Frame}">
                        <ContentPresenter x:Name="PART_FrameCP"/>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>

    <Window.DataContext>
        <local:MainViewModel/>
    </Window.DataContext>

    <DockPanel>
        <Border DockPanel.Dock="top" Background="AliceBlue" Padding="10">
            <StackPanel Orientation="Horizontal" >
                <Button Content="Page1" Padding="10 5" Margin="0 0 10 0"

                        Command="{Binding MenuCommand}" CommandParameter="Page1"/>
                <Button Content="Page2" Padding="10 5" Margin="0 0 10 0"

                        Command="{Binding MenuCommand}" CommandParameter="Page2"/>
            </StackPanel>
        </Border>
        <Frame Source="{Binding NavigateTo}" Style="{StaticResource FrameStyle1}" />
    </DockPanel>

</Window>



MainWindow的ViewModel


ViewModel for the MainWindow

using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.CommandWpf;

namespace WpfApp2
{
    public class MainViewModel : ViewModelBase
    {
        public MainViewModel()
        {
            MenuCommand = new RelayCommand<string>(msg => NavigateTo =


{msg} .xaml);
}

public RelayCommand< string> MenuCommand { get ; }

private string navigateTo = Page1.xaml;
public string NavigateTo
{
获取 = > navigateTo;
set = > 设置( ref navigateTo, value );
}
}
}
"{msg}.xaml"); } public RelayCommand<string> MenuCommand { get; } private string navigateTo = "Page1.xaml"; public string NavigateTo { get => navigateTo; set => Set(ref navigateTo, value); } } }



和两页(导航视图)


And the two Pages (Navigation Views)

<Page x:Class="WpfApp2.Page1"

      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 

      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 

      xmlns:local="clr-namespace:WpfApp2"

      mc:Ignorable="d" 

      d:DesignHeight="300" d:DesignWidth="300"

      Title="Page1">

    <Grid>
        <Viewbox>
            <TextBlock Text="Page 1"/>
        </Viewbox>
    </Grid>
</Page>

<Page x:Class="WpfApp2.Page2"

      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 

      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 

      xmlns:local="clr-namespace:WpfApp2"

      mc:Ignorable="d" 

      d:DesignHeight="300" d:DesignWidth="300"

      Title="Page2">

    <Grid>
        <Viewbox>
            <TextBlock Text="Page 2"/>
        </Viewbox>
    </Grid>
</Page>



现在我可以点击按钮,视图也会改变。



更新



再次阅读你的问题,我意识到你可能只想要子视图上的导航按钮。所以这是使用MVVMLight Messaging的另一种解决方案。 Messaging系统支持视图之间的简单通信。



MainWindow:


Now I can click on the buttons and the view will change.

Update

Having another read of your question I realise that you may only want the navigation buttons on the child views. So here is another solution using MVVMLight Messaging. The Messaging system enables simple communication between the views.

MainWindow:

<Window

    x:Class="WpfApp1.MainWindow"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"



    mc:Ignorable="d"

    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"



    xmlns:local="clr-namespace:WpfApp1"



    Title="WPF Navigation Example 2" Height="350" Width="525">

    <Window.Resources>
        <Style x:Key="FrameStyle1" TargetType="{x:Type Frame}">
            <Setter Property="BorderThickness" Value="0" />
            <Setter Property="NavigationUIVisibility" Value="Hidden" />
            <Setter Property="Margin" Value="0" />
            <Setter Property="SnapsToDevicePixels" Value="True" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Frame}">
                        <ContentPresenter x:Name="PART_FrameCP"/>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>

    <Window.DataContext>
        <local:MainViewModel/>
    </Window.DataContext>

    <DockPanel>
        <Frame Source="{Binding NavigateTo}" Style="{StaticResource FrameStyle1}" />
    </DockPanel>

</Window>



ViewModel for the MainWindow


ViewModel for the MainWindow

using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Messaging;

namespace WpfApp1
{
    public class MainViewModel : ViewModelBase
    {
        public MainViewModel()
        {
            Messenger.Default.Register<MenuNavigationMessage>
                (
                     this,
                     (navMsg) => NavigateTo =


\"{navMsg.Message}.xaml\"
);
}

private string navigateTo = \"Page1.xaml\";
public string NavigateTo
{
get => navigateTo;
set => Set(ref navigateTo, value);
}
}
}
"{navMsg.Message}.xaml" ); } private string navigateTo = "Page1.xaml"; public string NavigateTo { get => navigateTo; set => Set(ref navigateTo, value); } } }



The Messaging class used to pass typed messages between the viewmodels


The Messaging class used to pass typed messages between the viewmodels

namespace WpfApp1
{
    public class MenuNavigationMessage
    {
        public MenuNavigationMessage(string msg)
        {
            Message = msg;
        }
        public string Message { get; }
    }
}



A base view model for the navigation views with common functionality - messaging and buttons:


A base view model for the navigation views with common functionality - messaging and buttons:

using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;

namespace WpfApp1
{
    public abstract class NavigationViewModelBase : ViewModelBase
    {
        public NavigationViewModelBase()
        {
            MenuCommand = new RelayCommand<string>(msg => Messenger.Default.Send(new MenuNavigationMessage(msg)));
        }

        public RelayCommand<string> MenuCommand { get; }
    }
}



And the two Pages (Navigation Views)


And the two Pages (Navigation Views)

<Page x:Class="WpfApp1.Page1"

      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 

      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 

      xmlns:local="clr-namespace:WpfApp1"

      mc:Ignorable="d"  d:DesignHeight="300" d:DesignWidth="300"

      Title="Page1">

    <Page.DataContext>
        <local:Page1ViewModel/>
    </Page.DataContext>

    <Grid>
        <Button Content="Go to Page2" Padding="10 5" Margin="10"

                HorizontalAlignment="left" VerticalAlignment="Top"

                        Command="{Binding MenuCommand}" CommandParameter="Page2"/>
        <Viewbox>
            <TextBlock Text="Page 1"/>
        </Viewbox>
    </Grid>
</Page>

<Page x:Class="WpfApp1.Page2"

      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 

      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 

      xmlns:local="clr-namespace:WpfApp1"

      mc:Ignorable="d" 

      d:DesignHeight="300" d:DesignWidth="300"

      Title="Page2">

    <Page.DataContext>
        <local:Page2ViewModel/>
    </Page.DataContext>

    <Grid>
        <Button Content="Go to Page1" Padding="10 5" Margin="10"

                HorizontalAlignment="left" VerticalAlignment="Top"

                        Command="{Binding MenuCommand}" CommandParameter="Page1"/>
        <Viewbox>
            <TextBlock Text="Page 2"/>
        </Viewbox>
    </Grid>
</Page>



And the viewmodels for the pages


And the viewmodels for the pages

namespace WpfApp1
{
    public class Page1ViewModel : NavigationViewModelBase
    {
    }

    public class Page2ViewModel : NavigationViewModelBase
    {
    }
}



Now the navigation buttons are on each page. Clicking on them will switch the view.


Now the navigation buttons are on each page. Clicking on them will switch the view.


这篇关于如何执行不同类中的命令并绑定到不同窗口中的按钮?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆