Кнопка должна открывать новый ContentControl на основе шаблона MVVM в WPF C# - PullRequest
0 голосов
/ 19 июня 2020

Я хотел создать проект на основе паттерна MVVM. К сожалению, я не совсем понял это, и теперь у меня много последующих ошибок.

MainWindow.xaml

<Window x:Class="MyProject.MainWindow"
        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:MyProject"
        xmlns:viewmodels="clr-namespace:MyProject.ViewModels"
        xmlns:views="clr-namespace:MyProject.View"
        mc:Ignorable="d"
        Height="571.4" Width="730">

    <Window.Resources>
        <DataTemplate x:Name="Window1ViewTemplate" DataType="{x:Type viewmodels:Window1ViewModel}">
            <views:Window1View DataContext="{Binding}"/>
        </DataTemplate>
    </Window.Resources>

    <Grid>
        // Grid Definition not included - not relevant
        <DockPanel Background="Blue" Grid.Row="1" Grid.Column="0" Grid.RowSpan="3">
            <StackPanel>
                <Button Content="Window1" 
                        Height="45"
                        Click="Window1_click"/>
            </StackPanel>
        </DockPanel>

        <ContentControl Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="3" Grid.RowSpan="4" Content="{Binding}"/>

    </Grid>
</Window>

MainWindow.xaml.cs

namespace MyProject
{
    public partial class MainWindow : Window
    {

        public MainWindow()
        {
            InitializeComponent();
        }


        private void Window1_click(object sender, RoutedEventArgs e)
        {
            DataContext = new Window1ViewModel();
        }

    }
}

У меня есть окно, которое я назвал Window1. Думаю, это не совсем актуально.

Теперь кнопка Click Event правильно открывает окно. Но это не соответствует шаблону MVVM. Это запустит новый поток, который затем приведет к бесчисленному количеству последующих ошибок.

Как мне настроить событие кнопки, чтобы привязка снова была правильной.

1 Ответ

1 голос
/ 19 июня 2020

Некоторые предложения для вас.

  • Создайте класс MainViewModel и установите DataContext из MainWindow как экземпляр этого.
  • Если возможно, не Не используйте обработчики событий в MVVM, особенно для событий нажатия кнопок. Вместо этого в MainViewModel создайте свойство типа ICommand и привяжите к нему свойство кнопки Command.

В зависимости от того, какую (библиотеку) вы используете для реализации шаблона MVVM, возможно, у вас уже есть реализация ICommand, например MVVMLight's RelayCommand. Если нет, вы можете использовать базовую реализацию c ICommand, например

public class BasicCommand: ICommand
{
    private readonly Action _execute;

    public Command(Action execute)
    {
        _execute = execute;
    }

    public bool CanExecute(object parameter)
    {
        return true;
    }

    public void Execute(object parameter)
    {
        _execute?.Invoke();
    }

    public event EventHandler CanExecuteChanged;
}
  • В MainViewModel создайте свойство типа object ContentViewModel и привяжите к нему свойство Content ContenControl. Это свойство должно реализовывать INotifyPropertyChanged, поскольку вы собираетесь обновлять его из ViewModel.

  • В соответствующем методе для команды установите для свойства ContentViewModel соответствующее значение, например экземпляр Window1ViewModel.

  • В ресурсах ContentControl определите DataTemplate для каждого типа, который вы, возможно, захотите отобразить. Это должно быть основано на чем-то отличном от Window - например, Grid, CustomControl или UserControl.

.

 <ContentControl
    Margin="8"
    Content="{Binding SelectedItem}">
    <ContentControl.Resources>
        <DataTemplate DataType="{x:Type vm:Window1ViewModel}">
            <ctrl:Window1Display DataContext="{Binding}" />
        </DataTemplate>

        <DataTemplate DataType="{x:Type vm:Window2ViewModel}">
            <ctrl:Window2Display DataContext="{Binding}" />
        </DataTemplate>

        ...

    </ContentControl.Resources>
</ContentControl>

Дополнительные сведения и рабочий пример на моя запись в блоге .

...