首页 > 解决方案 > 如何在其他视图中多次使用具有相同功能的视图?

问题描述

我不确定这是否是正确的问题,但我不知道我还能怎么问。

在我的项目中,我有一个 LogInViewModel.cs

class LogInViewModel : BaseObservableObject
{
    private string _text;

    public string Text
    {
        get { return _text; }
        set { _text = value; OnPropertyChanged("Text"); }
    }

    public LogInViewModel()
    {
    }
}

一个 MenuViewModel.cs

class MenuViewModel : BaseObservableObject
{
    private string _text;

    public string Text
    {
        get { return _text; }
        set { _text = value; OnPropertyChanged("Text"); }
    }

    public LogInViewModel()
    {
    }
}

LogInView.xaml 和 MenuView.xaml 的视图是

<StackPanel>
    <TextBox Text="{Binding Text}"/>
    <local:NumPad/>
</StackPanel>

NumPad.xaml 是一个有 2 个按钮的 UserControl。

我想要的是,当我单击 LogInView 中的一个按钮时,我想将 LogInViewModel 的文本设置为某个字符串,而当我单击 MenuView 中的一个按钮时,我想将 MenuViewModel 的文本设置为某个字符串。我想创建一个带有多个按钮的 UserControl 键盘视图,并能够在多个视图中使用它,但是让它在它们所在的视图中的 TextBox 中添加字符(字符串),我可以像这样为我的 ViewModels 中的每个按钮创建 ICommands

class LogInViewModel : BaseObservableObject
{
    public ICommand SetTextCommand1 { get; set; }
    public ICommand SetTextCommand2 { get; set; }

    private string _text;
    public string Text
    {
        get { return _text; }
        set { _text = value; OnPropertyChanged("Text"); }
    }

    public LogInViewModel()
    {
        SetTextCommand1 = new BaseICommand(SetText1);
        SetTextCommand2 = new BaseICommand(SetText2);
    }

    private void SetText1(object obj)
    {
        Text = "1";
    }

    private void SetText2(object obj)
    {
        Text = "2";
    }
}

和 NumPad.xaml 将是

<StackPanel>
    <Button Command="{Binding SetTextCommand1}"/>
    <Button Command="{Binding SetTextCommand2}"/>
</StackPanel>

并将相同的 ICommands 添加到 MenuViewModel,但这似乎不正确,因为我希望我的 NumPad.xaml 最终成为一个带有很多按钮的键盘。

标签: c#wpfmvvm

解决方案


我认为,如果您想坚持使用命令,使用单个命令 + 使用参数控制它是更好的选择,例如:

<StackPanel>
    <Button Command="{Binding SetTextCommand}" CommandParameter="1" />
    <Button Command="{Binding SetTextCommand}" CommandParameter="2" />
</StackPanel>

class LogInViewModel : BaseObservableObject
{
    public ICommand SetTextCommand { get; set; }

    private string _text;
    public string Text
    {
        get { return _text; }
        set { _text = value; OnPropertyChanged("Text"); }
    }

    public LogInViewModel()
    {
        SetTextCommand1 = new BaseICommand(SetText);
    }

    private void SetText(object obj)
    {
        Text = obj?.ToString();
    }
}

无论如何,我建议将解决方案重构为更清洁的东西,例如:

  • 您的 NumPad 控件应定义公共事件或命令(如 KeyPressed)
  • 嵌入 NumPad 控件的控件(在您的情况下为 LogInView 和 MenuView)应显式使用/绑定 NumPad 的事件或命令
  • NumPad xaml 中的按钮应仅使用 NumPad 控件的 API;以您所做的方式在可重用控件中指定数据绑定类似于使用“魔术字符串”(例如,您必须确保每个 ViewModel 必须使用“SetTextCommand”名称定义命令,这很容易出错)

所以最后,你使用 NumPad 类似于:

<StackPanel>
    <TextBox Text="{Binding Text}"/>
    <local:NumPad KeyPressed="{Binding SetTextCommand}"/>
</StackPanel>

推荐阅读