c# - Cambie el control de usuario de una ventana dinĂ¡micamente en WPF(MVVM)
xaml user-controls (1)
Soy nuevo con WPF y solo estaba haciendo un menú simple usando MVVM con enlaces y comandos, pero creo que estoy haciendo algo mal. Solo quiero cambiar todo el contenido de la ventana importando un nuevo UserControl
que UserControl
, cada vez que presiono un botón de menú. Eso significa que quiero desaparecer el menú y mostrar un nuevo contenido (los UserControls que mencioné antes).
Bueno, tengo la ventana principal (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>
Este es uno de los UserControls que proporciona un menú de botones a la ventana principal cuando ejecuto el proyecto:
<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>
Este es el ViewModel Im que lo uso:
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
}
}
En App.xaml.cs cargamos la ventana principal:
public partial class App : Application
{
private void OnStartup(object sender, StartupEventArgs e)
{
ControlPanel view = new ControlPanel();
view.ShowDialog();
}
}
Ahora, el 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;
}
}
Muchas gracias.
Creo que el problema es que está intentando cambiar la propiedad de contenido de ContentControl, no la propiedad de su ViewModel. Ha conectado su ViewModel al Panel de control del host, pero también necesita los modelos de vista separados para los controles de usuario que se alojarán allí. Agregué la clase para el modelo de vista de control del usuario y cambié el nombre de la propiedad del modelo de vista del host por motivos de claridad. Corrija su código de la siguiente manera.
//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;
}
ventana principal 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>
Espero que sea bastante comprensible.