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

时间:2014-09-08 09:30:19

标签: c# wpf xaml mvvm user-controls

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

我有主窗口(ControlPanel):

<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;
    }
}

非常感谢。

1 个答案:

答案 0 :(得分:2)

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

//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>

希望它是可以理解的。