gpt4 book ai didi

c# - 使用子 ViewModel 创建 ViewModel

转载 作者:行者123 更新时间:2023-12-03 10:34:26 32 4
gpt4 key购买 nike

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

目标是:

我有一个主窗口。该窗口用于读取/创建图像。窗口上有一个按钮,可以在 2 个 UserControl 之间切换,一个带有 IHM 用于读取图像,另一个用于创建。

MainWindow 有一个 MainWindowViewModel :

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

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

    构造将是这样的:
    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 包含字段 ImageWidth,则 CreateUserControl 中的 ImageWidth 设置更改 ReadUserControl 的值。

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

    编辑1:

    我创建了 MainWindowViewModel作为单例,但我仍然无法获得 MainViewModel.CreateViewModelMainViewModel.ReadViewModel
    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
    }

    最佳答案

    您的示例将起作用。至少如果您已将 MainViewModel 设为 Singleton。

    更专业的方法可能是像这样的构造函数注入(inject)。

    public partial class ReadUserControl : UserControl
    {
    public ReadUserControl(MainViewModel vm)
    {
    InitializeComponent();
    DataContext = vm.ReadViewModel;
    }
    }

    使用此类 DependencyInjections,您可以实现更高级别的抽象,因为您的 UserControls 可以通用化。 (它们都将具有相同的构造函数)

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

    在您的特殊情况下,只将所需的参数传递给 UserControl 会更安全,而不是给他们一堆信息,他们永远不需要。
    public partial class ReadUserControl : UserControl
    {
    public ReadUserControl(Icommand command, int imageLength, AppParams appParams)
    {
    InitializeComponent();
    ...
    // Do with your Constructorparameters what ever you have to
    }
    }

    编辑:

    这里有一个小而笨的实现方法 可以做完了:

    代码
     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
     <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>

    关于c# - 使用子 ViewModel 创建 ViewModel,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38614294/

    32 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com