Как в WPF менять содержимое окна?

438
02 марта 2017, 22:06

Я новичек в технологии WPF, Есть приложение с лева есть меню, с множеством кнопок, с права пустое место для отображения представления, в зависимости какую кнопку меню нажали, появляется соответствующее представление.

Использую Catel, в котором во MainWindow.xaml использовал ContentControl в который помещал определенную вьюшку, не уверен что это правильно так как создавая вложенности в Catel перестает так работать, подскажите как можно реализовать такое поведение? или что я делаю не так?

Answer 1

Как и обещал в комментариях вот вам хоть и маленький, но вполне рабочий каркас приложения в духе MVVM, но безо всяких кателей и прочих фреймворков.

Это MainWindow.xaml

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <!--Меню-->
    <StackPanel Grid.Column="0" Margin="15">
        <Button Command="{Binding LoadMainUCCommand, Mode=OneTime}"
            Margin="10" Width="30" Height="30" HorizontalAlignment="Left">
            <TextBlock FontFamily="Segoe UI Symbol" FontSize="14">
                    <Run Text="&#xE0A5;" />
            </TextBlock>
        </Button>
        <Button Command="{Binding LoadFirstUCCommand, Mode=OneTime}"
            Margin="10" Width="30" Height="30" HorizontalAlignment="Left">
            <TextBlock FontFamily="Segoe UI Symbol" FontSize="14">
                    <Run Text="&#xE2AF;" />
            </TextBlock>
        </Button>
        <Button Command="{Binding LoadSecondUCCommand, Mode=OneTime}"
            Margin="10" Width="30" Height="30" HorizontalAlignment="Left">
            <TextBlock FontFamily="Segoe UI Symbol" FontSize="14">
                    <Run Text="&#xE1E2;" />
            </TextBlock>
        </Button>
    </StackPanel>
    <!--Контент-->
    <ContentPresenter Grid.Column="1" x:Name="OutputView" />
</Grid>

Это ее кодбихайнд

public interface IMainWindowsCodeBehind
{
    /// <summary>
    /// Показ сообщения для пользователя
    /// </summary>
    /// <param name="message">текст сообщения</param>
    void ShowMessage(string message);
    /// <summary>
    /// Загрузка нужной View
    /// </summary>
    /// <param name="view">экземпляр UserControl</param>
    void LoadView(ViewType typeView);
}
/// <summary>
/// Типы вьюшек для загрузки
/// </summary>
public enum ViewType
{
    Main,
    First,
    Second
}
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window, IMainWindowsCodeBehind
{
    public MainWindow()
    {
        InitializeComponent();
        this.Loaded += MainWindow_Loaded;
    }
    private void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
        //загрузка вьюмодел для кнопок меню
        MenuViewModel vm = new MenuViewModel();
        //даем доступ к этому кодбихайнд
        vm.CodeBehind = this;
        //делаем эту вьюмодел контекстом данных
        this.DataContext = vm;
        //загрузка стартовой View
        LoadView(ViewType.Main);
    }
    public void LoadView(ViewType typeView)
    {
        switch (typeView)
        {
            case ViewType.Main:
                //загружаем вьюшку, ее вьюмодель
                MainUC view = new MainUC();
                MainViewModel vm = new MainViewModel(this);
                //связываем их м/собой
                view.DataContext = vm;
                //отображаем
                this.OutputView.Content = view;
                break;
            case ViewType.First:
                FirstUC viewF = new FirstUC();
                FirstViewModel vmF = new FirstViewModel(this);
                viewF.DataContext = vmF;
                this.OutputView.Content = viewF;
                break;
            case ViewType.Second:
                SecondUC viewS = new SecondUC();
                SecondViewModel vmS = new SecondViewModel(this);
                viewS.DataContext = vmS;
                this.OutputView.Content = viewS;
                break;
        }

    }
    public void ShowMessage(string message)
    {
        MessageBox.Show(message);
    }
}

Вот где все команды перехода в MenuViewModel.cs

public class MenuViewModel
{
    //ctor
    public MenuViewModel()
    {
    }
    public IMainWindowsCodeBehind CodeBehind { get; set; }

    /// <summary>
    /// Переход к первой вьюшке
    /// </summary>
    private RelayCommand _LoadFirstUCCommand;
    public RelayCommand LoadFirstUCCommand
    {
        get
        {
            return _LoadFirstUCCommand = _LoadFirstUCCommand ??
              new RelayCommand(OnLoadFirstUC, CanLoadFirstUC);
        }
    }
    private bool CanLoadFirstUC()
    {
        return true;
    }
    private void OnLoadFirstUC()
    {
        CodeBehind.LoadView(ViewType.First);
    }

    /// <summary>
    /// Переход ко Второй вьюшке
    /// </summary>
    private RelayCommand _LoadSecondUCCommand;
    public RelayCommand LoadSecondUCCommand
    {
        get
        {
            return _LoadSecondUCCommand = _LoadSecondUCCommand ??
              new RelayCommand(OnLoadSecondUC, CanLoadSecondUC);
        }
    }
    private bool CanLoadSecondUC()
    {
        return true;
    }
    private void OnLoadSecondUC()
    {
        CodeBehind.LoadView(ViewType.Second);
    }

    /// <summary>
    /// Возвращение к главной вьюшке
    /// </summary>
    private RelayCommand _LoadMainUCCommand;
    public RelayCommand LoadMainUCCommand
    {
        get
        {
            return _LoadMainUCCommand = _LoadMainUCCommand ??
              new RelayCommand(OnLoadMainUC, CanLoadMainUC);
        }
    }
    private bool CanLoadMainUC()
    {
        return true;
    }
    private void OnLoadMainUC()
    {
        CodeBehind.LoadView(ViewType.Main);
    }
}

Это MainUC.xaml

<UserControl x:Class="ExampleMenu.View.MainUC"
         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:ExampleMenu.View"
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center">
    <TextBlock Text="Это начальная MainUC" FontSize="18" />
    <Button Content="Click Me" Command="{Binding ShowMessageCommand, Mode=OneTime}"
            Width="70" Height="20" Margin="0,20,0,0"/>
</StackPanel>

Вот ее ViewModel

public class MainViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged = delegate { };
    //Fields
    private IMainWindowsCodeBehind _MainCodeBehind;
    //ctor
    public MainViewModel(IMainWindowsCodeBehind codeBehind)
    {
        if (codeBehind == null) throw new ArgumentNullException(nameof(codeBehind));
        _MainCodeBehind = codeBehind;
    }
    //Properties
    //Commands
    /// <summary>
    /// Сообщение пользователю
    /// </summary>
    private RelayCommand _ShowMessageCommand;
    public RelayCommand ShowMessageCommand
    {
        get { return _ShowMessageCommand = _ShowMessageCommand ??
                new RelayCommand(OnShowMessage, CanShowMessage); }
    }
    private bool CanShowMessage()
    {
        return true;
    }
    private void OnShowMessage()
    {
        _MainCodeBehind.ShowMessage("Привет от MainUC");
    }
}

Весь проект можете скачать здесь.

READ ALSO
Как мокнуть класс без конструктора?

Как мокнуть класс без конструктора?

Проблема с классом DbContextConfiguration, этот класс не имеет public конструктораНо для задачи требуется мокнуть этот класс

337
Как в ComboBox добавлять элементы?

Как в ComboBox добавлять элементы?

У нас есть скромная формаА там скромный ComboBox

389
Что такое &ldquo;псевдоним&rdquo; для аргумента?

Что такое “псевдоним” для аргумента?

Читаю Джон Шарп - Microsoft Visual C#Подробное руководство - 2017

260