如何动态更改 wpf MVVM 灯中用户控件中存在的按钮(单击)上的用户控件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21107957/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 10:31:08  来源:igfitidea点击:

how to dynamically change userControl on button (click) present in the usercontrol in wpf MVVM light

c#wpfmvvmuser-controls

提问by Abhinav Sharma

I have a Main Window that host Usercontrol as ContentControl host.What i want is, to dynamically change usercontrol on button click(present in the first Usercontrol ) to another usercontrol.

我有一个主窗口,它将 Usercontrol 作为 ContentControl 主机托管。我想要的是,将按钮单击时的用户控件(出现在第一个 Usercontrol 中)动态更改为另一个用户控件。

Currently I have created a DataTemplate in the Main Window resources consisting of the respective ViewModel of the usercontrol

目前我在主窗口资源中创建了一个 DataTemplate,由用户控件的各个 ViewModel 组成

 

<DataTemplate DataType="{x:Type Tube:ViewModel1}" >
        <Tube:View1/>
 </DataTemplate>

 <DataTemplate DataType="{x:Type Tube1:ViewModel2}">
        <Tube2:View2/>
 </DataTemplate>

I want to change to from View1 to view2 on button click present in view1. So what should i do in ViewModel1(US1 viewModel) to change to US2

我想在视图 1 中的按钮单击时从视图 1 更改为视图 2。那么我应该在 ViewModel1(US1 viewModel) 中做什么来更改为 US2

I am currently working on MVVM light.

我目前正在研究 MVVM 灯。

I have a service locator that has the registered instance of each VM. The problem is how can i point to VM2 instance in VM1.

我有一个服务定位器,其中包含每个 VM 的注册实例。问题是我如何指向 VM1 中的 VM2 实例。

Any help is welcomed!!!!!

欢迎任何帮助!!!!!

采纳答案by Jossef Harush

Treat your Window as shell and send messages using MvvmLight's Messenger to your shell in order to swap views.

将您的窗口视为外壳,并使用 MvvmLight 的 Messenger 将消息发送到您的外壳以交换视图。

for example:

例如:

MainWindow.xaml

主窗口.xaml

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication1"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <local:MainWindowViewModel></local:MainWindowViewModel>
    </Window.DataContext>
    <Grid>

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>

        <Grid.RowDefinitions>
            <RowDefinition Height="20"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Button Grid.Row="0" Grid.Column="0" Command="{Binding ChangeFirstViewCommand}">Change View #1</Button>
        <Button Grid.Row="0" Grid.Column="1" Command="{Binding ChangeSecondViewCommand}">Change View #2</Button>
        <ContentControl  Grid.Row="1" Grid.ColumnSpan="2" Content="{Binding ContentControlView}"></ContentControl>
    </Grid>
</Window>

MainWindowViewModel.cs

主窗口视图模型.cs

using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;

namespace WpfApplication1
{
    public class MainWindowViewModel : ViewModelBase
    {
        private FrameworkElement _contentControlView;
        public FrameworkElement ContentControlView
        {
            get { return _contentControlView; }
            set
            {
                _contentControlView = value;
                RaisePropertyChanged("ContentControlView");
            }
        }

        public MainWindowViewModel()
        {
            Messenger.Default.Register<SwitchViewMessage>(this, (switchViewMessage) =>
            {
                SwitchView(switchViewMessage.ViewName);
            });
        }

        public ICommand ChangeFirstViewCommand
        {
            get
            {
                return new RelayCommand(() =>
                {
                    SwitchView("FirstView");

                });
            }
        }


        public ICommand ChangeSecondViewCommand
        {
            get
            {
                return new RelayCommand(() =>
                {
                    SwitchView("SecondView");
                });
            }
        }

        public void SwitchView(string viewName)
        {
            switch (viewName)
            {
                case "FirstView":
                    ContentControlView = new FirstView();
                    ContentControlView.DataContext = new FirstViewModel() { Text = "This is the first View" };
                    break;

                default:
                    ContentControlView = new SecondView();
                    ContentControlView.DataContext = new SecondViewModel() { Text = "This is the second View" };
                    break;
            }
        }
    }
}

FirstView.xaml

第一视图.xaml

<UserControl x:Class="WpfApplication1.FirstView"
             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" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <StackPanel>
        <Label>This is the second view</Label>
        <Label Content="{Binding Text}" />
        <Button Command="{Binding ChangeToSecondViewCommand}">Change to Second View</Button>
    </StackPanel>
</UserControl>

FirstViewModel.cs

FirstViewModel.cs

using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;

namespace WpfApplication1
{
    public class FirstViewModel : ViewModelBase
    {

        private string _text;
        public string Text
        {
            get { return _text; }
            set
            {
                _text = value;
                RaisePropertyChanged("Text");
            }
        }

        public ICommand ChangeToSecondViewCommand
        {
            get
            {
                return new RelayCommand(() =>
                {
                    Messenger.Default.Send<SwitchViewMessage>(new SwitchViewMessage { ViewName = "SecondView" });
                });
            }
        }
    }
}

SecondView.xaml

第二视图.xaml

<UserControl x:Class="WpfApplication1.SecondView"
             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" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <StackPanel>
        <Label>This is the second view</Label>
        <Label Content="{Binding Text}" />
        <Button Command="{Binding ChangeToFirstViewCommand}">Change to First View</Button>
    </StackPanel>
</UserControl>

SecondViewModel.cs

第二视图模型.cs

using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;

namespace WpfApplication1
{
    public class SecondViewModel : ViewModelBase
    {

        private string _text;
        public string Text
        {
            get { return _text; }
            set
            {
                _text = value;
                RaisePropertyChanged("Text");
            }
        }

        public ICommand ChangeToFirstViewCommand
        {
            get
            {
                return new RelayCommand(() =>
                {
                    Messenger.Default.Send<SwitchViewMessage>(new SwitchViewMessage { ViewName = "FirstView" });
                });
            }
        }
    }
}

SwitchViewMessage.cs

SwitchViewMessage.cs

namespace WpfApplication1
{
    public class SwitchViewMessage
    {
        public string ViewName { get; set; }
    }
}

回答by thoros1179

In your MainViewModel make a property eg "DisplayViewModel" with the basetype of your vm1 and vm2.

在您的 MainViewModel 中使用您的 vm1 和 vm2 的基本类型创建一个属性,例如“DisplayViewModel”。

private MyViewModelBase _displayViewModel;

public MyViewModelBase DisplayViewModel
{
    get { return _displayViewModel; }
    set 
    { 
        _displayViewModel = value;
        OnPropertyChanged("DisplayViewModel"); // Raise PropertyChanged
    }
}

In your MainView.xaml insert a ContentControl which binds to the DisplayViewModelProperty :

在您的 MainView.xaml 中插入一个绑定到 DisplayViewModelProperty 的 ContentControl :

<ContentControl Content="{Binding DisplayViewModel}" />

On your Button-Command you can Modify the DisplayProperty via Setter with another ViewModel and in combination with your DataTemplates the UserControl displayed by the ContentControl should change to the View according to the newly set ViewModel-Type.

在您的 Button-Command 上,您可以通过 Setter 使用另一个 ViewModel 修改 DisplayProperty,并结合您的 DataTemplates,ContentControl 显示的 UserControl 应根据新设置的 ViewModel-Type 更改为 View。

private void MyButtonCommand()
{
    DisplayViewModel = new ViewModel2();
}