将 UserControl 命令绑定到 MainWindow WPF/MVVM
Binding UserControl Command to MainWindow WPF/MVVM
我有一个 UserControl,它只是一个简单的 DataGrid 来显示一些东西,它有自己的 ViewModel 和 Model。
我想在每次单击 DataGrid 时引发一个事件。到目前为止,它正在使用命令,我在 UserControl.ViewModel.
上收到了事件
问题是我需要在 MainWindow.ViewModel 中引发事件,它包含加载 UserControl.DataGrid 中所需内容的逻辑。
以我对WPF和MVVM的一点了解,我有以下选择:
- UserControl.DataGridClicked 的 DependencyProperty(我想避免,并尽可能坚持使用 MVVM)
- 将 MainWindow.ViewModel 实例提供给我的 UserControl.ViewModel 的构造函数,这样我就可以直接引发事件。
- 创建一个 BusinessLogic Class,并将逻辑放在那里,这样我就可以在 UserControl.ViewModel 或 MainWindow.ViewModel 上调用它。
- ?
这就是我调用 UserControl 的方式:
<Window>
<Grid>
<TabControl>
<TabItem Header="{Binding Model.TabImportHeader}">
<views:ResultView DataContext="{Binding ResultViewModel}"/>
</TabItem>
</TabControl>
</Grid>
</Window>
这是我的用户控件:
<UserControl x:Class="ResultView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:viewModels="clr-namespace:ViewModels"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type=viewModels:ResultViewModel, IsDesignTimeCreatable=False}">
<!--DataGrid-->
<DataGrid ItemsSource="{Binding Model.ObservableCollection}"
ColumnWidth="*"
AutoGenerateColumns="false"
IsReadOnly="True"
BorderThickness="0"
Background="White"
HeadersVisibility="Column">
<!--InputBindings-->
<DataGrid.InputBindings>
<MouseBinding Gesture="LeftClick"
Command="{Binding LeftClickCommand}">
</MouseBinding>
</DataGrid.InputBindings>
<!--InputBindings-->
<DataGrid.Columns>
<DataGridTextColumn Header="Filename"
Binding="{Binding FileInfo.Name}"
Width="Auto" />
</DataGrid.Columns>
</DataGrid>
</UserControl>
有哪位WPF高手也懂一点好的做法?我将非常感谢任何帮助。
提前致谢。
编辑:命令声明:
public ICommand = new RelayCommand(LeftClick, () => true);
您可以使用 {RelativeSource}
:
直接绑定到 MainWindowViewModel
中的命令
<MouseBinding Gesture="LeftClick" Command="{Binding DataContext.CommandPropertyInMainWindowVm, RelativeSource={RelativeSource AncestorType=Window}}" />
或者您可以绑定到 UserControlViewModel
的命令,该命令使用事件聚合器或消息总线发布事件。然后 MainWindowViewModel
将订阅此事件。请参阅以下博客 post 了解更多相关信息:https://blog.magnusmontin.net/2014/02/28/using-the-event-aggregator-pattern-to-communicate-between-view-models/.
使用事件聚合器在两个组件(例如两个视图模型)之间进行通信,消除了事件发布者和订阅者之间的紧密耦合。两个视图模型都有对事件聚合器的引用,但它们彼此之间没有任何关系。这是在 MVVM 中以松耦合方式在视图模型之间进行通信的最佳实践。
您将需要一个事件聚合器实现。大多数 MVVM 库都包含一个。在 Prism the class is called EventAggregator
. In Mvvm Light it's called Messenger
: https://marcominerva.wordpress.com/2014/06/25/how-to-send-string-and-content-messages-with-mvvm-light-messenger/。不过概念是一样的。
我有一个 UserControl,它只是一个简单的 DataGrid 来显示一些东西,它有自己的 ViewModel 和 Model。
我想在每次单击 DataGrid 时引发一个事件。到目前为止,它正在使用命令,我在 UserControl.ViewModel.
上收到了事件问题是我需要在 MainWindow.ViewModel 中引发事件,它包含加载 UserControl.DataGrid 中所需内容的逻辑。
以我对WPF和MVVM的一点了解,我有以下选择:
- UserControl.DataGridClicked 的 DependencyProperty(我想避免,并尽可能坚持使用 MVVM)
- 将 MainWindow.ViewModel 实例提供给我的 UserControl.ViewModel 的构造函数,这样我就可以直接引发事件。
- 创建一个 BusinessLogic Class,并将逻辑放在那里,这样我就可以在 UserControl.ViewModel 或 MainWindow.ViewModel 上调用它。
- ?
这就是我调用 UserControl 的方式:
<Window>
<Grid>
<TabControl>
<TabItem Header="{Binding Model.TabImportHeader}">
<views:ResultView DataContext="{Binding ResultViewModel}"/>
</TabItem>
</TabControl>
</Grid>
</Window>
这是我的用户控件:
<UserControl x:Class="ResultView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:viewModels="clr-namespace:ViewModels"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type=viewModels:ResultViewModel, IsDesignTimeCreatable=False}">
<!--DataGrid-->
<DataGrid ItemsSource="{Binding Model.ObservableCollection}"
ColumnWidth="*"
AutoGenerateColumns="false"
IsReadOnly="True"
BorderThickness="0"
Background="White"
HeadersVisibility="Column">
<!--InputBindings-->
<DataGrid.InputBindings>
<MouseBinding Gesture="LeftClick"
Command="{Binding LeftClickCommand}">
</MouseBinding>
</DataGrid.InputBindings>
<!--InputBindings-->
<DataGrid.Columns>
<DataGridTextColumn Header="Filename"
Binding="{Binding FileInfo.Name}"
Width="Auto" />
</DataGrid.Columns>
</DataGrid>
</UserControl>
有哪位WPF高手也懂一点好的做法?我将非常感谢任何帮助。
提前致谢。
编辑:命令声明:
public ICommand = new RelayCommand(LeftClick, () => true);
您可以使用 {RelativeSource}
:
MainWindowViewModel
中的命令
<MouseBinding Gesture="LeftClick" Command="{Binding DataContext.CommandPropertyInMainWindowVm, RelativeSource={RelativeSource AncestorType=Window}}" />
或者您可以绑定到 UserControlViewModel
的命令,该命令使用事件聚合器或消息总线发布事件。然后 MainWindowViewModel
将订阅此事件。请参阅以下博客 post 了解更多相关信息:https://blog.magnusmontin.net/2014/02/28/using-the-event-aggregator-pattern-to-communicate-between-view-models/.
使用事件聚合器在两个组件(例如两个视图模型)之间进行通信,消除了事件发布者和订阅者之间的紧密耦合。两个视图模型都有对事件聚合器的引用,但它们彼此之间没有任何关系。这是在 MVVM 中以松耦合方式在视图模型之间进行通信的最佳实践。
您将需要一个事件聚合器实现。大多数 MVVM 库都包含一个。在 Prism the class is called EventAggregator
. In Mvvm Light it's called Messenger
: https://marcominerva.wordpress.com/2014/06/25/how-to-send-string-and-content-messages-with-mvvm-light-messenger/。不过概念是一样的。