首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >创建带有子ViewModel的ViewModel

创建带有子ViewModel的ViewModel
EN

Stack Overflow用户
提问于 2016-07-27 13:25:03
回答 2查看 1.1K关注 0票数 1

是否有适当的方法来创建包含ViewModel的C#/WPF subViewModel?

目标是:

我有一个MainWindow。该窗口用于读取/创建图像。该窗口上有一个按钮,它在两个UserControl之间切换--一个用于读取图像,另一个用于创建。

MainWindow有一个MainWindowViewModel,它具有:

  • 命令开关
  • 图像长度
  • 应用参数

我希望两个UserControls都可以访问MainWindowViewModel字段/属性,并拥有它们自己的命令。

建筑将是这样的:

代码语言:javascript
复制
public partial class ReadUserControl : UserControl
{
    public ReadUserControl()
    {
        InitializeComponent();
        DataContext = MainViewModel.ReadViewModel;
    }
}

public partial class CreateUserControl : UserControl
{
    public CreateUserControl()
    {
        InitializeComponent();
        DataContext = MainViewModel.CreateViewModel;
    }
}

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = MainViewModel;
    }
}

例如,如果MainViewModel包含在CreateUserControl中设置ImageWidth的字段ImageWidth,则更改ReadUserControl的值。

我希望已经说清楚了,我不知道如何设计我的MainViewModel来达到这个结果

EDIT1:

我已经将MainWindowViewModel创建为一个单例,但我仍然无法获得MainViewModel.CreateViewModelMainViewModel.ReadViewModel

代码语言:javascript
复制
public class MainWindowViewModel : ViewModelBase
{   
    private static MainWindowViewModel _instance = null;
    public static MainWindowViewModel Instance
    {
        get
        {
            if (_instance == null)
                _instance = new MainWindowViewModel();
            return _instance;
        }
    }
    private MainWindowViewModel()
        : base()
    {
    }

    #region CreateViewModel
    /* How to create ? */
    #endregion
    #region ReadViewModel
    /* How to create ? */
    #endregion
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-07-27 13:35:34

你的榜样会奏效的。至少如果你已经把你的MainViewModel变成了单身。

更专业的方法可能是像这样的构造器注入。

代码语言:javascript
复制
public partial class ReadUserControl : UserControl
{
    public ReadUserControl(MainViewModel vm)
    {
        InitializeComponent();
        DataContext = vm.ReadViewModel;
    }
}

使用这样的DependencyInjections,您可以实现更高级别的抽象,因为您的UserControls可以被泛化。(它们都有相同的构造函数)

另一方面,您给每个这样的UserControl能力,操纵MainViewModel,而不知道副作用。

在您的特殊情况下,只向UserControl传递所需的参数将更加安全,而不是给它们一堆信息,它们将永远不需要。

代码语言:javascript
复制
public partial class ReadUserControl : UserControl
    {
        public ReadUserControl(Icommand command, int imageLength, AppParams appParams)
        {
            InitializeComponent();
            ...
            // Do with your Constructorparameters what ever you have to
        }
}

编辑:

这里是一个如何实现的小的、愚蠢的实现:

代码语言:javascript
复制
 public class MainViewModel : INotifyPropertyChanged {
    private INotifyPropertyChanged _selectedViewModel;

    public MainViewModel() {
      var cmd = new RelayCommand(x => {
        MessageBox.Show("HelloWorld");
      }, x => true);
      this.RVM = new ReadViewModel(cmd);
      this.WVM = new WriteViewModel(cmd);
      this.SelectedViewModel = WVM;
    }

    private ICommand _switchViewModelCommand;

    public ICommand SwitchViewModelCommand => this._switchViewModelCommand ?? (this._switchViewModelCommand = new RelayCommand(x => {
      if (this.SelectedViewModel == RVM) {

        this.SelectedViewModel = WVM;
        return;
      }
      this.SelectedViewModel = RVM;
    }));

    public INotifyPropertyChanged SelectedViewModel {
      get {
        return this._selectedViewModel;
      }
      set {
        if (Equals(value, this._selectedViewModel))
          return;
        this._selectedViewModel = value;
        this.OnPropertyChanged();
      }
    }

    public ReadViewModel RVM {
      get; set;
    }

    public WriteViewModel WVM {
      get; set;
    }

    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) {
      this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
  }

  public class ReadViewModel : INotifyPropertyChanged {
    public ReadViewModel(ICommand sayHelloCommand) {
      this.HelloCommand = sayHelloCommand;
    }

    public ICommand HelloCommand {
      get;
    }

    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) {
      this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
  }

  public class WriteViewModel : INotifyPropertyChanged {

    public WriteViewModel(ICommand sayHelloCommand) {
      this.HelloCommand = sayHelloCommand;
    }

    public ICommand HelloCommand {
      get;
    }

    public ICommand HelloMoonCommand => new RelayCommand(x => { MessageBox.Show("Hello Moon"); });

    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) {
      this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

    }
  }

XAML

代码语言:javascript
复制
 <Window.DataContext>
        <local:MainViewModel/>
    </Window.DataContext>

    <Grid Height="200">
        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>
        <ContentControl Content="{Binding SelectedViewModel, UpdateSourceTrigger=PropertyChanged}">
            <ContentControl.Resources>
                <DataTemplate DataType="{x:Type local:ReadViewModel}">
                    <StackPanel>
                        <Button Content="Say Hello world" Command="{Binding HelloCommand}"></Button>
                    </StackPanel>
                </DataTemplate>
                <DataTemplate DataType="{x:Type local:WriteViewModel}">
                    <StackPanel>
                        <Button Content="Say Hello world" Command="{Binding HelloCommand}"></Button>
                        <Button Content="Say Hello Moon" Command="{Binding HelloMoonCommand}"></Button>
                    </StackPanel>
                </DataTemplate>
            </ContentControl.Resources>
        </ContentControl>
        <Button Content="Switch VM" Command="{Binding SwitchViewModelCommand}" Grid.Row="1"/>
    </Grid>
票数 1
EN

Stack Overflow用户

发布于 2016-07-27 13:38:14

您可以将MainViewModel作为用户控件传入DataContext,并将元素的数据上下文设置为Read/Create模型。

就像这样

代码语言:javascript
复制
<Grid> <!--using MainWindowViewModel as data context-->
    <Grid DataContext="{Binding Path=CreateViewModel}"> <!--using CreateViewModel as data context-->
          .....
    </Grid>
<Grid>
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38614294

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档