Выбор WPF DataGridComboboxColumn завершается ошибкой, если используется перетаскивание

У меня есть Usercontrol с TabControl, включая Datagrid для каждого tabItem. Datagrid имеет 3 столбца, один из которых представляет собой столбец со списком.

<UserControl x:Name="ConfigurationView"
         x:Class="HyperPostHelper.Controls.ConfigurationControl"
         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:viewModel="clr-namespace:HyperPostHelper.ViewModel"
         mc:Ignorable="d"
         d:DesignHeight="300" d:DesignWidth="300"
         ClipToBounds="True"
         HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
         Width="auto" Height="auto"
         Margin="5">
<Grid>
    <TabControl x:Name="ConfigurationTab" ItemsSource="{Binding Path=ConfigurationFiles, UpdateSourceTrigger=PropertyChanged}">
        <TabControl.ItemTemplate>
            <DataTemplate>
                <TextBlock FontWeight="Bold" Text="{Binding FileName, UpdateSourceTrigger=PropertyChanged}" />
            </DataTemplate>
        </TabControl.ItemTemplate>
        <TabControl.ContentTemplate>
            <DataTemplate>
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="30" />
                        <RowDefinition Height="*" />
                        <RowDefinition Height="30" />
                    </Grid.RowDefinitions>



                    <DataGrid Name="ConfigurationFileView"
                              Grid.Row="1"
                              Margin="2"
                              AutoGenerateColumns="False"
                              ItemsSource="{Binding Parameters,
                                                    UpdateSourceTrigger=PropertyChanged}"
                              SelectedItem="{Binding SelectedItem,
                                                     UpdateSourceTrigger=PropertyChanged}"
                              AllowDrop="True" PreviewMouseLeftButtonDown="ConfigurationFileView_PreviewMouseLeftButtonDown"
                              Drop="ConfigurationFileView_Drop">
                        <DataGrid.RowStyle>
                            <Style TargetType="DataGridRow">
                                <Style.Triggers>
                                    <DataTrigger Binding="{Binding IsValid, UpdateSourceTrigger=PropertyChanged}" Value="true">
                                        <Setter Property="Background" Value="White" />
                                    </DataTrigger>
                                    <DataTrigger Binding="{Binding IsValid, UpdateSourceTrigger=PropertyChanged}" Value="false">
                                        <Setter Property="Background" Value="Red" />
                                    </DataTrigger>
                                </Style.Triggers>
                            </Style>
                        </DataGrid.RowStyle>
                        <DataGrid.Columns>
                            <DataGridTextColumn Binding="{Binding Name, UpdateSourceTrigger=PropertyChanged}" Header="Name" />
                            <DataGridComboBoxColumn SelectedItemBinding="{Binding Path=Type, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Header="Type">
                                <DataGridComboBoxColumn.ElementStyle>
                                    <Style TargetType="ComboBox">
                                        <Setter Property="ItemsSource" Value="{Binding ElementName=ConfigurationView, Path=DataContext.Types}" />
                                    </Style>
                                </DataGridComboBoxColumn.ElementStyle>
                                <DataGridComboBoxColumn.EditingElementStyle>
                                    <Style TargetType="ComboBox">
                                        <Setter Property="ItemsSource" Value="{Binding ElementName=ConfigurationView, Path=DataContext.Types}" />
                                    </Style>
                                </DataGridComboBoxColumn.EditingElementStyle>
                            </DataGridComboBoxColumn>
                            <DataGridTextColumn Binding="{Binding Value, UpdateSourceTrigger=PropertyChanged}" Header="Value" Width="*" />
                        </DataGrid.Columns>
                    </DataGrid>
                    <Grid Grid.Row="2">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="30" />
                            <ColumnDefinition Width="30" />
                            <ColumnDefinition Width="auto" />
                        </Grid.ColumnDefinitions>
                        <Button Name="AddParameter"
                                Grid.Row="2" Grid.Column="0"
                                Margin="2"
                                Command="{Binding Path=AddParameterCommand}"
                                Style="{DynamicResource FlatButtonStyle}">
                            <Button.ToolTip>
                                <TextBlock>Adds a new parametert to the selected list</TextBlock>
                            </Button.ToolTip>
                            <Grid>
                                <Image Width="20" Height="20" Source="..\Resources\Property-Add.png" />
                            </Grid>
                        </Button>
                        <!--<Button Name="DeleteParameter" Grid.Row="2" Grid.Column="1" Margin="2" Command="{Binding Path=DeleteParameterCommand}" Style="{DynamicResource FlatButtonStyle}">
                        <Button.ToolTip>
                            <TextBlock>Deletes a selected parameter from the selected list</TextBlock>
                        </Button.ToolTip>
                        <Grid>
                            <Image Width="20" Height="20" Source="..\Resources\Property-Delete.png" />
                        </Grid>
                    </Button>-->
                    </Grid>

                </Grid>
            </DataTemplate>

        </TabControl.ContentTemplate>
    </TabControl>
</Grid>

Now I've implemented some Drag&Drop feature for moving the rows using PreviewMouseLeftButtonDown and Drop event. With that the Drag&Drop is working fine. But I can't select with the mouse from the combobox any more, the box opens and I can see the content but if I want to select an Item with the mouse it's selecting the datagridrow beneath the selectedItem of dropdown list. With the up/down key from the keyboard I can select.

private void ConfigurationFileView_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        DependencyObject source = e.OriginalSource as DependencyObject;
        while (source != null && !(source is System.Windows.Controls.ComboBox))
            source = VisualTreeHelper.GetParent(source);
        if (source != null)
        {
            // don't know what to do here....
        }
        else
        {
            DataGrid dataGrid = (DataGrid)sender;                

            rowIndex = GetCurrentRowIndex(dataGrid, e.GetPosition);
            if (rowIndex < 0)
                return;
            dataGrid.SelectedIndex = rowIndex;
            ParameterVM selectedEmp = dataGrid.Items[rowIndex] as ParameterVM;
            if (selectedEmp == null)
                return;
            DragDropEffects dragdropeffects = DragDropEffects.Move;
            if (DragDrop.DoDragDrop(dataGrid, selectedEmp, dragdropeffects) != DragDropEffects.None)
            {
                dataGrid.SelectedItem = selectedEmp;
            }
        }

    } 

private void ConfigurationFileView_Drop(object sender, DragEventArgs e)
    {
        DataGrid dataGrid = (DataGrid)sender;

        int index = this.GetCurrentRowIndex(dataGrid, e.GetPosition);
        if (index < 0)
            return;

        if (rowIndex < 0)
        {
            ParameterVM newParameter = e.Data.GetData(typeof(ParameterVM))as ParameterVM;
            if (null == newParameter)
                return;

            ObservableCollection<ParameterVM> parameters = dataGrid.ItemsSource as ObservableCollection<ParameterVM>;
            if (!parameters.Any(p => p.Name == newParameter.Name && p.Type == newParameter.Type))
            {
                parameters.Insert(index, newParameter);    
            }                

        }
        else
        {
            if (index == rowIndex)
                return;
            if (index == dataGrid.Items.Count - 1)
            {
                MessageBox.Show("This row-index cannot be drop");
                return;
            }

            ObservableCollection<ParameterVM> parameters = dataGrid.ItemsSource as ObservableCollection<ParameterVM>;
            ParameterVM changedParameter = parameters[rowIndex];
            parameters.Move(rowIndex, index);
        }
    }

Я уже прочитал здесь ответ, чтобы проверить, является ли объект зависимости полем со списком или нет. Я пробовал так, но я не знаю, что делать дальше, чтобы выделение с помощью мыши работало правильно.


person Björn Engelke    schedule 03.04.2015    source источник


Ответы (1)


Наконец я нашел решение, которое работает для меня.

Я добавил два события в DataGrid:

BeginningEdit="ConfigurationFileView_BeginningEdit" CellEditEnding="ConfigurationFileView_CellEditEnding"

Также добавлен код:

public bool IsEditing { get; set; }

    private void ConfigurationFileView_BeginningEdit(object sender, DataGridBeginningEditEventArgs e)
    {
        IsEditing = true;
    }

    private void ConfigurationFileView_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
    {
        IsEditing = false;
    }

И в DropEvent я добавил if относительно значения IsEditing:

private void ConfigurationFileView_Drop(object sender, DragEventArgs e)
        {
            if (IsEditing)
                return;

            DataGrid dragSource = e.Data.GetData("DragSource") as DataGrid;
            if (null == dragSource)
                return;

            DataGrid dropTarget = sender as DataGrid;
            if (null == dropTarget)
                return;

            int index = this.GetCurrentRowIndex(dropTarget, e.GetPosition);
            if (index < 0)
                return;            

            .....
        }
person Björn Engelke    schedule 10.04.2015