如何使用WPF和MVVM进行一些简单的布局和操作?

时间:2011-08-15 06:50:58

标签: wpf winforms mvvm

我刚开始研究WPF和MVVM,我正在考虑我需要开始使用MVVM。

我有一个winform应用程序,主面板,主面板左侧有一些按钮,主面板右侧是一个区域,用于放置不同的子面板(一次一个面板),单击主窗体按钮后,将调用子面板的方法。

是否可以使用MVVM进行此类布局和操作?

3 个答案:

答案 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

  • 中显示的ChildViewModel显示ChildViews

由于主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中的绑定语法那样简单。如果这是正确的方向,我会保留你的意见。