我刚开始研究WPF和MVVM,我正在考虑我需要开始使用MVVM。
我有一个winform应用程序,主面板,主面板左侧有一些按钮,主面板右侧是一个区域,用于放置不同的子面板(一次一个面板),单击主窗体按钮后,将调用子面板的方法。
是否可以使用MVVM进行此类布局和操作?
答案 0 :(得分:1)
不确定。左侧和右侧面板都将绑定到单个ViewModel(即代表右侧当前面板的VM)。左侧的按钮将调用ViewModel上的操作(可能通过命令)。
当活动VM更改时(即,右侧显示不同的面板时),左侧面板的数据上下文将更改为新VM。
您可能希望某种容器VM代表整个窗口,其中几个子ViewModel代表右侧的每个可能的面板。在任何给定时间,只有其中一个被设置为活动面板。这有意义吗?
答案 1 :(得分:1)
主ViewModel将包含
的属性ViewModelBase CurrentPage
ICommand ChangePageCommand
ObservableCollection<ViewModelBase> AvailablePages
主视图将包含
ContentControl
用于托管CurrentPage
AvailablePages
点击“菜单”区域中的链接会调用ChangePage
命令将CurrentPage
切换为所选的AvailablePage
。
DataTemplates
将根据CurrentPage
由于主ViewModel可以访问所有可用页面,因此可以根据需要在ChildViewModel上执行方法,并且可以从ChildViewModels中调用ChangePageCommand
如果您有兴趣,我写了一个这样的界面here的示例,尽管它只显示了切换CurrentPage
的示例,而不是导航AvailablePages
答案 2 :(得分:0)
第一次抱歉误会。我创建了一个小样本。这是XAML代码:
<Window x:Class="S4SO.ContainerBinding.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="520" Width="425">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="80" />
<RowDefinition Height="400" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="400" />
</Grid.ColumnDefinitions>
<ContentControl Content="{Binding ContentContent}" Grid.Row="1" Height="400" Width="400" />
<StackPanel Orientation="Horizontal">
<Button Content="Use button" Command="{Binding UseButton}" />
<Button Content="Use Textbox" Command="{Binding UseTextbox}" />
</StackPanel>
</Grid>
</Window>
窗口绑定到viewmodel,为简单起见,我将MVVMLight作为基础:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
using System.Windows.Controls;
using System.Windows;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight;
namespace S4SO.ContainerBinding {
public class ViewModel : ViewModelBase {
private object _ContentContent;
public object ContentContent {
get { return _ContentContent; }
set {
if ( _ContentContent.GetType() == value.GetType() )
return;
_ContentContent = value;
RaisePropertyChanged( "ContentContent" );
}
}
public ICommand UseButton { get; set; }
public void CommandUseButton () {
ContentContent = new Button() {
Content = "A button",
Width = 400,
Height = 400,
VerticalContentAlignment = VerticalAlignment.Center,
HorizontalContentAlignment = HorizontalAlignment.Center
};
}
public bool CanUseButton () {
return !( _ContentContent is Button );
}
public ICommand UseTextbox { get; set; }
public void CommandUseTextbox () {
ContentContent = new TextBox() {
Text = "Content here",
Width = 400,
Height = 400,
VerticalContentAlignment = VerticalAlignment.Center,
HorizontalContentAlignment = HorizontalAlignment.Center
};
}
public bool CanUseTextbox () {
return !( _ContentContent is TextBox );
}
public ViewModel () {
_ContentContent = new Label() {
Content = "Please choose content!",
Width = 400,
Height = 400,
HorizontalContentAlignment = HorizontalAlignment.Center,
VerticalContentAlignment = VerticalAlignment.Center
};
UseButton = new RelayCommand( () => CommandUseButton(), () => CanUseButton() );
UseTextbox = new RelayCommand( () => CommandUseTextbox(), () => CanUseTextbox() );
}
}
}
绝对不是生产水平,但它显示了一个方向,希望现在更符合您的要求。我使用了简单的控件,并没有深入研究那些动态创建的控件。通过代码绑定并不像XAML中的绑定语法那样简单。如果这是正确的方向,我会保留你的意见。