c# - 在 WPF (MVVM) 中动态更改窗口的用户控件

标签 c# wpf xaml mvvm user-controls

我是 WPF 的新手,我只是使用带有绑定(bind)命令MVVM 做一个简单的菜单> 但我觉得我做错了什么。每次按下菜单按钮时,我只想更改所有导入我定义的新 UserControl 的窗口内容。这意味着我想消失菜单并显示新内容(我之前提到的 UserControls)。

我有主窗口(控制面板):

<Window x:Class="OfficeMenu.Views.Menu.ControlPanel"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Control Panel" Height="800" Width="800">
<Grid>

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

</Grid>
</Window>

这是在我运行项目时向主窗口提供按钮菜单的 UserControls 之一:

<UserControl x:Class="OfficeMenu.Views.ButtonsMenu"
         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">
<UserControl.Resources>
    <!-- One style for each *type* of control on the window -->
    <Style TargetType="Button">
        <Setter Property="Margin" Value="5"/>
    </Style>

</UserControl.Resources>
 <Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="1*" />
        <ColumnDefinition Width="1*" />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="1*" />
        <RowDefinition Height="1*" />
    </Grid.RowDefinitions>
    <Button Command="{Binding OpenUsersCommand}">BUTTON 1</Button>
    <Button Grid.Column="1">BUTTON 2</Button>
    <Button Grid.Column="1" Grid.Row="2" >BUTTON 3</Button>
    <Button Grid.Row="1">BUTTON 4</Button>
</Grid>
</UserControl>

这是我使用的 ViewModel:

class MenuViewModel : ViewModelBase
{
    RandomModel _model;  <!-- It does nothing important -->
    private UserControl _content;

    public ICommand OpenUsersCommand { get; private set; }

    public UserControl Content
    {
        get { return _content; }
        set {
            _content = value;
            NotifyPropertyChanged("contentWindow");
        }
    }

    public MenuViewModel(RandomModel model )
    {
        this._model= model;
        OpenUsersCommand = new RelayCommand(OpenUsers,null);
    }

    private void OpenUsers()
    {
        Content = new UsersPanel();  //This is the UserControl we need to load dinamically
    }
}

在 App.xaml.cs 中我们加载主窗口:

public partial class App : Application
{

    private void OnStartup(object sender, StartupEventArgs e)
    {
        ControlPanel view = new ControlPanel();
        view.ShowDialog();
    }
}

现在,controlPanel.xaml.cs:

public ControlPanel()
    {
        InitializeComponent();

        ModelRandom model = new ModelRandom(); <!-- It does nothing yet -->
        MenuViewModel viewmodel = new MenuViewModel(model);
        Content = new BottonsMenu();  <!-- We load a default UserControl when we run the program -->
        this.DataContext = viewmodel;
    }
}

非常感谢。

最佳答案

我认为问题在于您正在尝试更改 ContentControl 的 Content 属性,而不是 ViewModel 的属性。您已将 ViewModel 连接到主机 ControlPanel,但您还需要单独的 View 模型用于将托管在那里的用户控件。为了清楚起见,我为用户控制 View 模型添加了类并更改了主机的 View 模型属性名称。按如下方式更正您的代码。

//host view model
class MainModel : ViewModelBase
{
    private UserControl _content;

    public MainModel() { }

    internal void SetNewContent(UserControl _content)
    {
        ContentWindow = _content;
    }

    public UserControl ContentWindow
    {
        get { return _content; }
        set
        {
            _content = value;
            OnPropertyChanged("ContentWindow");
        }
    }
}

//user contol's view model
class MenuViewModel : ViewModelBase
{
    MainModel _mainModel;
    RandomModel _model; // <!-- It does nothing important -->

    public ICommand OpenUsersCommand { get; private set; }


    public MenuViewModel(MainModel mainModel, RandomModel model )
    {
        this._mainModel = mainModel;
        this._model = model;
        OpenUsersCommand = new RelayCommand(OpenUsers, CanOpenUsers);
    }

    private void OpenUsers(object _param)
    {
        UsersPanelViewModel upmodel = new UsersPanelViewModel(_mainModel, _model);
        UsersPanel up = new UsersPanel();
        up.DataContext = upmodel;
        _mainModel.SetNewContent(up);
    }

    private bool CanOpenUsers(object _param)
    {
        return true;
    }
}

    //main window function
    public ControlPanel()
    {
        InitializeComponent();

        //create main view model for host
        MainModel mainModel = new MainModel();

        RandomModel model = new RandomModel(); //<!-- It does nothing yet -->

        //create view model for user controls
        MenuViewModel viewmodel = new MenuViewModel(mainModel, model);
        ButtonsMenu bm = new ButtonsMenu(); // <!-- We load a default UserControl when we run the program -->
        bm.DataContext = viewmodel;

        //set host's property in our user control
        mainModel.ContentWindow = bm;
        this.DataContext = mainModel;
    }

主窗口 XAML

<Window x:Class="WpfApplication1.ControlPanel"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <ContentControl Content="{Binding ContentWindow}"/>
    </Grid>
</Window>

希望它很容易理解。

关于c# - 在 WPF (MVVM) 中动态更改窗口的用户控件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25721128/

相关文章:

c# - 应用程序启动检查,我应该在 MVVM 模式中的什么地方执行它们?

wpf - 如何绑定(bind) WPF 中另一个程序集中的类的属性?

c# - 在 xmlns clr 命名空间 : 中找不到 Xamarin Forms 抛出异常

javascript - 如何将参数传递给 PdfAction.JavaScript(jscode, stapmer.Writer)

c# - 错误 CS7069 : Reference to type 'x' claims it is defined in 'y' , 但找不到; MSBuild 14

c# - 将事件GotFocus分配给WPF应用程序中的所有文本框

xaml - UWP 的日历日期选择器

c# - 使用绑定(bind)到 List<UserControl> 我该怎么做才能不显示控件

javascript - 按下删除键时 ASP.NET MVC 未知操作

c# - MVC Core IActionResult 含义