DataGrid mvvm / wpf中ComboBox上的SelectionChanged的EventToCommand

时间:2017-02-24 21:48:43

标签: c# wpf mvvm combobox datagrid

如何捕获嵌入ComboBox的{​​{1}}触发的Selection Changed事件?我想为此使用MVVM模式,所以类似DataGridComboBoxColum解决方案会很好。

XAML:

EventToCommmand

我想使用这样的东西但不知道在这种特殊情况下在何处/如何设置它。

<DataGridComboBoxColumn Header="ViewTemplate" Width="180" SelectedItemBinding="{Binding ViewTemplate}" DisplayMemberPath="Name">
    <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>

根据要求,这是我对XAML的完整代码:

<i:Interaction.Triggers>
    <i:EventTrigger EventName="SelectionChanged">
        <cmd:EventToCommand PassEventArgsToCommand="True" Command="{Binding SelectionChangedCommand}"/>
    </i:EventTrigger>
</i:Interaction.Triggers>

并查看模型:

<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>

3 个答案:

答案 0 :(得分:2)

使用MVVM模式,您不会处理视图中SelectionChanged元素的ComboBox事件。

相反,您应该在ViewTemplate属性的setter中或在您从那里调用的方法中实现选择更改的逻辑,只要在ComboBox中选择了新项,就会设置该逻辑, .eg:

private ViewWrapper _viewTemplate;
public ViewWrapper ViewTemplate
{
    get { return _viewTemplate; }
    set { _viewTemplate = value; SelectionChanged(); }
}

这是MVVM的基石之一。只要视图设置了source属性,视图模型就可以执行某些逻辑。视图仅设置属性。它不处理任何事件。

修改:如果出于某种原因这不是一个选项,则应将DataGridComboBoxColumn替换为DataGridTemplateColumn,因为您无法将EventTrigger应用于{ {1}}:

Style

答案 1 :(得分:0)

您可以将eventhandler添加到组合框中。我添加到grid的显示事件,当然可以添加另一个事件。

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);
                }
}}

答案 2 :(得分:0)

我会做的是这样的事情 所以在你的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知道它引用的位置,以便它可以看到SelectionChangeCommand所在的位置,以便它可以进行绑定。仅供参考,对于relaycommand,我的建议是使用Galasoft.MVVMlight,这样你就不必自己实现relaycommand。