如果使用拖放,WPF DataGridComboboxColumn selction 将失败
WPF DataGridComboboxColumn selction fails if Drag&Drop is used
我有一个带有 TabControl 的 Usercontrol,包括每个 tabItem 的 Datagrid。
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>
现在我已经使用 PreviewMouseLeftButtonDown 和 Drop 事件实现了一些用于移动行的拖放功能。这样,拖放就可以正常工作了。但是我不能再使用组合框中的鼠标 select,该框打开并且我可以看到内容,但是如果我想 select 使用鼠标的项目它是 selecting selectedItem 下拉列表下方的数据网格。使用键盘上的 up/down 键,我可以 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);
}
}
我已经在这里阅读了一个答案来检查依赖对象是否是一个组合框。我试过了,但我不知道该怎么做才能通过鼠标 selection 运行 正确。
最后我找到了适合我的解决方案。
我向 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 中我添加了一个关于 IsEditing 值的 if:
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;
.....
}
我有一个带有 TabControl 的 Usercontrol,包括每个 tabItem 的 Datagrid。 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>
现在我已经使用 PreviewMouseLeftButtonDown 和 Drop 事件实现了一些用于移动行的拖放功能。这样,拖放就可以正常工作了。但是我不能再使用组合框中的鼠标 select,该框打开并且我可以看到内容,但是如果我想 select 使用鼠标的项目它是 selecting selectedItem 下拉列表下方的数据网格。使用键盘上的 up/down 键,我可以 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);
}
}
我已经在这里阅读了一个答案来检查依赖对象是否是一个组合框。我试过了,但我不知道该怎么做才能通过鼠标 selection 运行 正确。
最后我找到了适合我的解决方案。
我向 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 中我添加了一个关于 IsEditing 值的 if:
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;
.....
}