c# - DataGrid mvvm/wpf 内的 ComboBox 上的 SelectionChanged 的​​ EventToCommand

标签 c# wpf mvvm combobox datagrid

如何捕获在嵌入到 DataGridComboBoxColum 中的 ComboBox 上触发的 Selection Changed 事件?我想为此使用 MVVM 模式,因此像 EventToCommmand 解决方案会很好。

XAML:

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

我想使用类似的东西,但不知道在这种特殊情况下在哪里/如何设置它。

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

和 View 模型:

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

最佳答案

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

相反,您应该在 ViewTemplate 属性的 setter 中或在从那里调用的方法中实现选择更改逻辑,每当在 中选择新项目时就会设置该逻辑组合框,例如:

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

这是 MVVM 的基石之一。每当 View 设置源属性时, View 模型就可以执行一些逻辑。 View 仅设置一个属性。它不处理任何事件。

编辑:如果由于某种原因这不是一个选项,您应该将 DataGridComboBoxColumn 替换为 DataGridTemplateColumn,因为您无法应用 >EventTriggerStyle:

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

关于c# - DataGrid mvvm/wpf 内的 ComboBox 上的 SelectionChanged 的​​ EventToCommand,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42448877/

相关文章:

java - Dagger MVVM - ViewModel 注入(inject)为空

c# - 数据表未被填充

c# - 如何将值附加到 Excel 范围

.net - 在WPF中绘制像素

c# - 异步图像加载到列表框中

wpf - 带有 DataGrid WPF 的复选框

wpf - 组合框中的项目分组

c# - 即使内容比容器高,WPF 控件也会对齐到底部

c# - 这个单例实现是线程安全的吗 - 检查代码

c# - 有关使用 WCF 服务的 MVVM 模式的一般问题