как да промените динамично userControl върху бутон (щракване), присъстващ в usercontrol в wpf MVVM light

Имам главен прозорец, който хоства Usercontrol като ContentControl хост. Това, което искам, е динамично да променя потребителския контрол при щракване на бутон (наличен в първия Usercontrol) на друг потребителски контрол.

В момента създадох DataTemplate в ресурсите на главния прозорец, състоящ се от съответния ViewModel на потребителския контрол

 

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

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

Искам да променя от View1 на view2 при щракване върху бутон, присъстващ в view1. И така, какво трябва да направя в ViewModel1 (US1 viewModel), за да променя на US2

В момента работя върху MVVM light.

Имам локатор на услуги, който има регистрирания екземпляр на всяка виртуална машина. Проблемът е как мога да посоча към екземпляр на VM2 във VM1.

Всяка помощ е добре дошла!!!!!


person Abhinav Sharma    schedule 14.01.2014    source източник
comment
каква беше общата VM за тези изгледи?   -  person Sankarann    schedule 14.01.2014
comment
Има 3 VM, 1 Main VM за MainWIndow и 2 US VIewModel за съответните изгледи   -  person Abhinav Sharma    schedule 14.01.2014
comment
@Sankarann ​​Редактирах въпроса....   -  person Abhinav Sharma    schedule 14.01.2014


Отговори (2)


Отнасяйте се към своя Window като към обвивка и изпращайте съобщения с помощта на Messenger на MvvmLight до вашата обвивка, за да разменяте изгледи.

например:

MainWindow.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

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

<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

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

<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

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

namespace WpfApplication1
{
    public class SwitchViewMessage
    {
        public string ViewName { get; set; }
    }
}
person Jossef Harush    schedule 14.01.2014

Във вашия MainViewModel направете свойство, например "DisplayViewModel" с основния тип на вашите vm1 и vm2.

private MyViewModelBase _displayViewModel;

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

Във вашия MainView.xaml вмъкнете ContentControl, който се свързва с DisplayViewModelProperty:

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

На вашата Button-Command можете да модифицирате DisplayProperty чрез Setter с друг ViewModel и в комбинация с вашите DataTemplates UserControl, показван от ContentControl, трябва да се промени на View според новозададения ViewModel-Type.

private void MyButtonCommand()
{
    DisplayViewModel = new ViewModel2();
}
person thoros1179    schedule 14.01.2014
comment
Съжалявам, че погрешно съм разбрал, че бутонът ви не е на основния ви модел на изглед. - person thoros1179; 14.01.2014
comment
Ако вашият MainViewModel знае и двата ViewModels vm1 и vm2, можете да приложите събитие SwitchViewModel във вашите vm1 и vm2 и да задействате това събитие при команда на бутон. Във вашия манипулатор на събития в MainViewModel можете след това да промените своето свойство DisplayViewModel, което кара потребителския интерфейс да превключи към другия UserControl според DataTemplate. - person thoros1179; 14.01.2014