【问题标题】:MVVM Pattern: Commands for several GUI events?MVVM 模式:几个 GUI 事件的命令?
【发布时间】:2023-03-28 19:20:01
【问题描述】:

我已经做了很多winform和很多WPF(MVC风格)。

我研究了 MVVM 模式,目前,我唯一坚持的是Commands

我遇到的问题是我没有找到合适的方法来为许多事件抛出命令。

我找不到如何调用命令,即业务上下文中的交互。

例如: 我有以下 MVVM 模型:

public class MyDemoViewModel : DependencyObject{
    private IDataManager _manager;
    private static readonly DependencyProperty _currentMessageDependancyProperty = DependencyProperty.Register("CurrentMessage", typeof(String), typeof(MyDemoViewModel), new PropertyMetadata(""));

    public ICommand SendMessageCommand{get; private set;}
    public String CurrentMessage {
            get { return(String) GetValue(_currentMessageDependancyProperty); }
            set { SetValue(_currentMessageDependancyProperty, value); }
        }

    public MyDemoViewModel(IDataManager manager){
        _manager= manager;
        SendMessageCommand = new SendMessageCommand(this);
    }

    public void SendMessage(String message){
        _manager.SendMessage(message);
        CurrentMessage = String.Empty;
    }
}

用一个简单的命令:

public class SendMessageCommand :ICommand{
    private MyDemoViewModel _model;

    public SendMessageCommand(MyDemoViewModel model) {
        _model = model;
    }

    public event EventHandler CanExecuteChanged {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    public bool CanExecute(object parameter)
    {
        return !String.IsNullOrEmpty(_model.CurrentMessage);
    }

    public void Execute(object parameter)
    {
        _model.SendMessage( _model.CurrentMessage );
    }
}

还有一个基本的 XAML:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="2*"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <TextBox Grid.Row="1" TextWrapping="Wrap" Text="{Binding CurrentMessage, UpdateSourceTrigger=PropertyChanged}"/>
    <Button Content="Send" Grid.Column="1"  Grid.Row="1" Command="{Binding SendMessageCommand}"/>
</Grid>

当有人在 TextBox 中按下 Enter 键时,我应该怎么做(我的意思是,根据 MVVM 模式)来执行我的命令?我的意思是,通常我会在“TextChanged”上设置一个事件并在后面的代码中发送命令。但我不想在不了解模型/业务逻辑的情况下保留我的代码。

这是我做过的最简单的例子,但我可能对其他操作有同样的需求(可能无法通过简单按钮访问的操作)。

谢谢

【问题讨论】:

  • 我通常使用AttachedCommand 来实现这种功能。它允许您将命令绑定到 UI 中的几乎任何事件。如果您不介意使用混合库,Interaction.Triggers 也是一个可行的选择。

标签: c# wpf xaml mvvm command-pattern


【解决方案1】:

对于您的具体示例,您可以使用InputBindings。这些允许您执行一些命令以响应手势(通常是键盘或鼠标)。以下是实现您所追求的快速示例:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="2*"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <TextBox Grid.Row="1" TextWrapping="Wrap" Text="{Binding CurrentMessage, UpdateSourceTrigger=PropertyChanged}">
        <TextBox.InputBindings>
            <KeyBinding Command="{Binding SendMessageCommand}" Key="Return" />
            <KeyBinding Command="{Binding SendMessageCommand}" Key="Enter" />
        </TextBox.InputBindings>
    </TextBox>
    <Button Content="Send" Grid.Column="1"  Grid.Row="1" Command="{Binding SendMessageCommand}"/>
</Grid>

对于更高级的情况,例如对各种 UI 事件做出反应,您可以使用 Expression Blends Interactivity 命名空间(请参阅here):

<TextBox>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="GotFocus">
            <i:EventTrigger.Actions>
                <i:InvokeCommandAction Command="{Binding SendMessageCommand}" />
            </i:EventTrigger.Actions>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</TextBox>

可以在 NuGet here 上找到 Blend SDK 的非官方版本。

【讨论】:

  • 哦,非常好! ListBox 是否有这种用于 SelectedItem 事件的 InputBindings?
  • 要对事件做出反应,您可能需要使用 Blends 交互功能,并带有 &lt;i:EventTrigger EventName="SelectionChanged"&gt;,然后在反应中执行命令。
  • 另一种选择是将ListBoxSelectedItem 绑定到视图模型中的一个属性,并在选择一个属性时执行一些操作
  • 是否有可能并建议“注册/监听”我模型的依赖属性?
  • 通常视图模型实现 INotifyPropertyChanged 并且不派生自 DependencyObject,请参阅 here 以了解模型和视图模型所扮演的角色。
猜你喜欢
  • 2020-05-30
  • 1970-01-01
  • 1970-01-01
  • 2013-11-09
  • 1970-01-01
  • 1970-01-01
  • 2011-09-02
  • 2012-06-17
  • 1970-01-01
相关资源
最近更新 更多