C# 在DataGrid mvvm/wpf内的组合框上更改了用于选择的EventToCommand
如何捕获在嵌入到C# 在DataGrid mvvm/wpf内的组合框上更改了用于选择的EventToCommand,c#,wpf,mvvm,combobox,datagrid,C#,Wpf,Mvvm,Combobox,Datagrid,如何捕获在嵌入到DataGridComboBoxColum中的组合框上触发的Selection Changed事件?我想为此使用MVVM模式,因此类似于eventtocommand的解决方案会很好 XAML: 我想使用类似的东西,但不知道在这种特殊情况下在何处/如何设置它 <i:Interaction.Triggers> <i:EventTrigger EventName="SelectionChanged"> <cmd:EventToC
DataGridComboBoxColum
中的组合框上触发的Selection Changed事件?我想为此使用MVVM模式,因此类似于eventtocommand
的解决方案会很好
XAML:
我想使用类似的东西,但不知道在这种特殊情况下在何处/如何设置它
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<cmd:EventToCommand PassEventArgsToCommand="True" Command="{Binding SelectionChangedCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
根据要求,这是我的XAML完整代码:
<UserControl x:Class="GrimshawRibbon.Revit.Views.ViewManager.ViewManagerView"
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:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:local="clr-namespace:GrimshawRibbon.Revit.Views.ViewManager"
xmlns:ex="clr-namespace:GrimshawRibbon.Revit.Wpf.Extensions"
xmlns:controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Platform"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="500">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Colors.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/Blue.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseLight.xaml" />
<ResourceDictionary Source="pack://application:,,,/GrimshawRibbon;component/Revit/Wpf/Style/GrimshawTheme.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<ex:DataGridEx x:Name="dgViews"
Style="{StaticResource AzureDataGrid}"
Margin="10"
AutoGenerateColumns="False"
ItemsSource="{Binding Views, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
CanUserAddRows="False"
IsReadOnly="False"
SelectionMode="Extended"
SelectionUnit="FullRow"
SelectedItemsList="{Binding SelectedViews, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="CellEditEnding">
<cmd:EventToCommand PassEventArgsToCommand="True" Command="{Binding CellEditEndingCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="*"/>
<DataGridTextColumn Header="ViewType" Binding="{Binding ViewType}" Width="100" IsReadOnly="True"/>
<DataGridTextColumn Header="ViewGroup" Binding="{Binding ViewGroup, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="130" IsReadOnly="False"/>
<DataGridTextColumn Header="ViewSubGroup" Binding="{Binding ViewSubGroup, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="130" IsReadOnly="False"/>
<DataGridCheckBoxColumn ElementStyle="{DynamicResource MetroDataGridCheckBox}"
EditingElementStyle="{DynamicResource MetroDataGridCheckBox}"
Header="OnSheet"
Binding="{Binding OnSheet, Mode=TwoWay}"
IsReadOnly="True"
Width="80">
</DataGridCheckBoxColumn>
<DataGridComboBoxColumn Header="ViewTemplate" Width="180" SelectedItemBinding="{Binding ViewTemplate}" DisplayMemberPath="Name">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<cmd:EventToCommand PassEventArgsToCommand="True" Command="{Binding DataContext.SelectChangeCommand, RelativeSource={RelativeSource AncestorType=UserControl}}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<DataGridComboBoxColumn.ElementStyle>
<Style TargetType="{x:Type ComboBox}" BasedOn="{StaticResource {x:Type ComboBox}}">
<Setter Property="ItemsSource" Value="{Binding DataContext.ViewTemplates, RelativeSource={RelativeSource AncestorType=DataGrid}}"/>
<Setter Property="IsReadOnly" Value="True"/>
</Style>
</DataGridComboBoxColumn.ElementStyle>
<DataGridComboBoxColumn.EditingElementStyle>
<Style TargetType="{x:Type ComboBox}" BasedOn="{StaticResource {x:Type ComboBox}}">
<Setter Property="ItemsSource" Value="{Binding DataContext.ViewTemplates, RelativeSource={RelativeSource AncestorType=DataGrid}}"/>
</Style>
</DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>
</DataGrid.Columns>
</ex:DataGridEx>
</Grid>
</UserControl>
和视图模型:
public class ViewManagerViewModel : ViewModelBaseEx
{
public ViewManagerModel Model;
public ObservableCollection<ViewWrapper> Views { get; private set; }
public ObservableCollection<ViewWrapper> ViewTemplates { get; private set; }
public IList SelectedViews { get; set; }
public RelayCommand<DataGridCellEditEndingEventArgs> CellEditEndingCommand { get; set; }
public RelayCommand<SelectionChangedEventArgs> SelectChangeCommand { get; set; }
public ViewManagerViewModel(Document doc)
{
Model = new ViewManagerModel(doc);
Views = Model.CollectViews();
ViewTemplates = Model.CollectViewTemplates();
CellEditEndingCommand = new RelayCommand<DataGridCellEditEndingEventArgs>(args => OnCellEditEnding(args));
SelectChangeCommand = new RelayCommand<SelectionChangedEventArgs>(args => OnSelectionChanged(args));
}
private void OnSelectionChanged(SelectionChangedEventArgs e)
{
// do something
}
/// <summary>
/// Logic for handling cell editing events.
/// </summary>
/// <param name="e">DataGrid Row object.</param>
private void OnCellEditEnding(DataGridCellEditEndingEventArgs e)
{
var wrapper = e.Row.Item as ViewWrapper;
switch (e.Column.SortMemberPath)
{
case "Name":
Model.ChangeName(wrapper);
break;
case "ViewGroup":
Model.SetParameter(wrapper, "View Group", wrapper.ViewGroup);
break;
case "ViewSubGroup":
Model.SetParameter(wrapper, "View Sub Group", wrapper.ViewSubGroup);
break;
default:
break;
}
}
public override void Apply()
{
var vw = new List<ViewWrapper>();
foreach (ViewWrapper v in SelectedViews)
{
vw.Add(v);
}
Model.Delete(vw);
// update collection so that rows get deleted in datagrid
foreach (ViewWrapper i in vw)
{
Views.Remove(i);
}
}
}
公共类ViewManagerViewModel:ViewModelBaseEx
{
公共视图管理器模型;
公共可观测集合视图{get;private set;}
公共ObservableCollection视图模板{get;private set;}
公共IList SelectedViews{get;set;}
public RelayCommand CellEditEndingCommand{get;set;}
public RelayCommand selectchange命令{get;set;}
公共视图管理器视图模型(文档文档)
{
模型=新的ViewManagerModel(文档);
视图=Model.CollectViews();
ViewTemplates=Model.CollectViewTemplates();
CellEditEndingCommand=newrelaycommand(args=>OnCellEditEnding(args));
选择ChangeCommand=new RelayCommand(args=>OnSelectionChanged(args));
}
SelectionChanged上的私有无效(SelectionChangedEventArgs e)
{
//做点什么
}
///
///处理单元格编辑事件的逻辑。
///
///DataGrid行对象。
私有void onCelledEnding(DataGridCelledEndingEventArgs e)
{
var wrapper=e.Row.Item作为ViewWrapper;
开关(例如Column.SortMemberPath)
{
案例“名称”:
Model.ChangeName(包装器);
打破
案例“视图组”:
SetParameter(包装器,“视图组”,包装器.ViewGroup);
打破
案例“ViewSubGroup”:
SetParameter(wrapper,“视图子组”,wrapper.ViewSubGroup);
打破
违约:
打破
}
}
公共覆盖无效应用()
{
var vw=新列表();
foreach(选定视图中的视图包装器v)
{
增加(v);
}
删除型号(vw);
//更新集合,以便在datagrid中删除行
foreach(大众汽车中的视图包装器i)
{
意见。删除(i);
}
}
}
您可以将eventhandler添加到组合框中。我添加到网格的显示事件中,您当然可以添加另一个事件
private void Grid1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
ComboBox cb = e.Control as ComboBox;
if (cb!=null)
{ cb.SelectionChangeCommitted -= new EventHandler(cb_SelectedIndexChanged);
// now attach the event handler
cb.SelectionChangeCommitted += new EventHandler(cb_SelectedIndexChanged);
}
}}
我会这样做 因此,在viewmodel中,您将有如下内容 Viewmodel.cs
public class ViewModel
{
public ViewModel()
{
_selectChangeCommand= new RelayCommand(OnSelectChange, CanSelectChange);
}
private RelayCommand _selectChangeCommand;
public ICommand SelectChangeCommand { get { return _selectChangeCommand; } }
private bool CanSelectChange()
{
return true;
}
private void OnSelectChange()
{
..//do something in here when you change something in your combo box
}
}
在MainWindow.xaml.cs中
这样做:
this.DataContext = new ViewModel();
在ViewModel.xaml文件中
<ComboBox....>
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<cmd:EventToCommand PassEventArgsToCommand="True" Command="{Binding SelectChangeCommand }"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ComboBox>
一件重要的事情是确保viewmodel.xaml知道它从何处引用,以便它可以看到selectionchange命令位于何处,从而可以进行绑定。仅供参考,对于relaycommand,我的建议是使用Galasoft.MVVMlight,这样您就不必自己实现relaycommand。使用MVVM模式,您不必处理视图中
组合框
元素的SelectionChanged
事件
相反,您应该在ViewTemplate
属性的setter中实现更改选择逻辑,或者在从那里调用的方法中实现更改选择逻辑,该方法在组合框中选择新项时设置。例如:
private ViewWrapper _viewTemplate;
public ViewWrapper ViewTemplate
{
get { return _viewTemplate; }
set { _viewTemplate = value; SelectionChanged(); }
}
这是MVVM的基石之一。只要视图设置了源属性,视图模型就可以执行一些逻辑。该视图仅设置一个属性。它不处理任何事件
编辑:如果出于某种原因这不是一个选项,则应将DataGridComboxColumn
替换为DataGridTemplateColumn
,因为您无法将事件触发器
应用于样式
:
<DataGridTemplateColumn Header="ViewTemplate" Width="180">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding ViewTemplate.Name}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding DataContext.ViewTemplates, RelativeSource={RelativeSource AncestorType=DataGrid}}"
SelectedItem="{Binding ViewTemplate}"
DisplayMemberPath="Name">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<cmd:EventToCommand PassEventArgsToCommand="True"
Command="{Binding DataContext.SelectionChangedCommand, RelativeSource={RelativeSource AncestorType=DataGrid}}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
所以,这是我一直在寻找的方法,但不幸的是,它没有触发我的命令。还有什么我需要在这里做的吗?发布你的代码,我会看一看!我可以建议你做的一件事是查看输出窗口并查找命令名。。。VisualStudio上的“输出”窗口将确切地告诉您为什么命令没有触发ViewModel和View的完整代码。谢谢你的帮助!嗯,我并不是在试图处理这个问题。我试图在视图中设置绑定,以便它能够在视图模型中触发适当的命令。可以吗?不可以。关键是不应该使用EventTrigger来调用命令。当组合框中的选择发生更改时,您应该在源属性(ViewTemplate)的setter中调用该命令,因为该属性将被设置
<DataGridTemplateColumn Header="ViewTemplate" Width="180">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding ViewTemplate.Name}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding DataContext.ViewTemplates, RelativeSource={RelativeSource AncestorType=DataGrid}}"
SelectedItem="{Binding ViewTemplate}"
DisplayMemberPath="Name">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<cmd:EventToCommand PassEventArgsToCommand="True"
Command="{Binding DataContext.SelectionChangedCommand, RelativeSource={RelativeSource AncestorType=DataGrid}}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>