WPF将UI事件绑定到ViewModel中的命令

Ben*_*Ben 52 c# wpf mvvm

我正在做一些简单的应用程序重构以跟随MVVM,我的问题是如何将SelectionChanged事件从我的代码中移出到viewModel?我已经看了一些绑定元素到命令的例子,但是并没有完全掌握它.谁能帮忙解决这个问题.谢谢!

有人可以使用下面的代码提供解决方案吗?非常感谢!

public partial class MyAppView : Window 
{
    public MyAppView()
    {
        InitializeComponent();

        this.DataContext = new MyAppViewModel ();

        // Insert code required on object creation below this point.
    }

    private void contactsList_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
    {
        //TODO: Add event handler implementation here.           
        //for each selected contact get the labels and put in collection 

        ObservableCollection<AggregatedLabelModel> contactListLabels = new ObservableCollection<AggregatedLabelModel>();

        foreach (ContactListModel contactList in contactsList.SelectedItems)
        {
            foreach (AggregatedLabelModel aggLabel in contactList.AggLabels)
            {
                contactListLabels.Add(aggLabel);
            }
        }
        //aggregate the contactListLabels by name
        ListCollectionView selectedLabelsView = new ListCollectionView(contactListLabels);

        selectedLabelsView.GroupDescriptions.Add(new PropertyGroupDescription("Name"));
        tagsList.ItemsSource = selectedLabelsView.Groups;
    }
}
Run Code Online (Sandbox Code Playgroud)

Pav*_*kov 109

您应该EventTriggerInvokeCommandActionWindows.Interactivity命名空间结合使用.这是一个例子:

<ListBox ...>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="SelectionChanged">
            <i:InvokeCommandAction Command="{Binding SelectedItemChangedCommand}"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</ListBox>
Run Code Online (Sandbox Code Playgroud)

你可以System.Windows.Interactivity去参考Add reference > Assemblies > Extensions.

完整的i命名空间是:xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity".

  • 您还需要定位.net framework 4.0.即使您使用的是Blend4,此行为操作也不在3.5框架中 (4认同)

Cam*_*and 10

这个问题有类似的问题.

WPF MVVM:命令很简单.如何使用RoutedEvent连接View和ViewModel

我处理这个问题的方法是在ViewModel中有一个SelectedItem属性,然后将ListBox的SelectedItem绑定到该属性.


Sni*_*son 10

我知道现在有点晚了,但是 Microsoft 已将其 Xaml.Behaviors 开源,现在只需一个命名空间即可轻松使用交互性。

  1. 首先将 Microsoft.Xaml.Behaviors.Wpf Nuget packge 添加到您的项目中。
    https://www.nuget.org/packages/Microsoft.Xaml.Behaviors.Wpf/
  2. 将 xmlns:behaviours="http://schemas.microsoft.com/xaml/behaviors" 命名空间添加到您的 xaml 中。

然后像这样使用它,

<Button Width="150" Style="{DynamicResource MaterialDesignRaisedDarkButton}">
   <behaviours:Interaction.Triggers>
       <behaviours:EventTrigger EventName="Click">
           <behaviours:InvokeCommandAction Command="{Binding OpenCommand}" PassEventArgsToCommand="True"/>
       </behaviours:EventTrigger>
    </behaviours:Interaction.Triggers>
    Open
</Button>
Run Code Online (Sandbox Code Playgroud)

PassEventArgsToCommand="True" 应设置为 True,并且您实现的 RelayCommand 可以采用 RoutedEventArgs 或对象作为模板。如果您使用对象作为参数类型,只需将其转换为适当的事件类型。

该命令看起来像这样,

OpenCommand = new RelayCommand<object>(OnOpenClicked, (o) => { return true; });
Run Code Online (Sandbox Code Playgroud)

命令方法看起来像这样,

private void OnOpenClicked(object parameter)
{
    Logger.Info(parameter?.GetType().Name);
}
Run Code Online (Sandbox Code Playgroud)

“参数”将是路由事件对象。

如果你好奇的话,还有日志,

2020-12-15 11:40:36.3600|信息|MyApplication.ViewModels.MainWindowViewModel|RoatedEventArgs

如您所见,记录的 TypeName 是 RoutedEventArgs

RelayCommand 的实现可以在这里找到。

为什么选择 RelayCommand

PS:您可以绑定到任何控件的任何事件。就像Window的Closing事件一样,你会得到相应的事件。


dec*_*one 7

你最好的选择是使用Windows.Interactivity.使用EventTriggers一个连接ICommand到任何RoutedEvent.

这篇文章是为了帮助您入门:Silverlight和WPF行为和触发器


M. *_*ley 7

要重构这个,你需要改变你的想法.您将不再处理"选择已更改"事件,而是将所选项目存储在viewmodel中.然后,您将使用双向数据绑定,以便在用户选择项目时更新您的viewmodel,并在更改所选项目时更新您的视图.


Jok*_*ang 6

考虑Microsoft.Xaml.Behaviors.WpfMicrosoft您可以在该页面中看到它的所有者。

System.Windows.Interactivity.WPF所有者是mthamil,谁能告诉我它可靠吗?

示例Microsoft.Xaml.Behaviors.Wpf

<UserControl ...
             xmlns:behaviors="http://schemas.microsoft.com/xaml/behaviors"
             ...>

<Button x:Name="button">
    <behaviors:Interaction.Triggers>
        <behaviors:EventTrigger EventName="Click" SourceObject="{Binding ElementName=button}">
            <behaviors:InvokeCommandAction Command="{Binding ClickCommand}" />
        </behaviors:EventTrigger>
    </behaviors:Interaction.Triggers>
</Button>

</UserControl>
Run Code Online (Sandbox Code Playgroud)

  • System.Windows.Interactivity 由 Micrososft Blend/Expression 团队维护,近年来他们将其开源并重新打包为 nuget Microsoft.Xaml.Behaviours.Wpf,请查看[此博客](https://devblogs. microsoft.com/dotnet/open-source-xaml-behaviors-for-wpf/) 了解更多信息 (5认同)