在鼠标滚动时自动检查和取消选中WPF DataGrid中的复选框

时间:2016-07-23 10:20:46

标签: c# wpf xaml checkbox datagrid

我正在开发一个WPF应用程序,我需要只向那些在DataGrid中检查过的联系人发送短信。

在DataGrid中检查所需的联系人后,当我向下/向上滚动时,我遇到了问题。 DataGrid中复选框的checked属性随机更改。

我遇到了一些建议添加以下属性的解决方案:

  • VirtualizingStackPanel.VirtualizationMode = DataGrid中的“标准”
  • DataGrid中的VirtualizingStackPanel.IsVirtualizing =“True”(当我将其设置为False时,应用程序变得完全没有响应)
  • CheckBox绑定中的UpdateSourceTrigger =“PropertyChanged”
  • DataGrid中的EnableRowVirtualization =“True”
  • DataGrid中的EnableColumnVirtualization =“True”

我尝试了所有这些,但没有一个能够奏效。

XAML:

<StackPanel Orientation="Horizontal">
        <DataGrid x:Name="smsgrid" VirtualizingStackPanel.VirtualizationMode="Standard" VirtualizingStackPanel.IsVirtualizing="True" Margin="10,20,0,10" AutoGenerateColumns="False" IsReadOnly="True" CanUserResizeColumns="False" CanUserReorderColumns="False" CanUserSortColumns="False">
            <DataGrid.Columns>
                <DataGridTemplateColumn>
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <CheckBox x:Name="chkbox" Checked="chkbox_Checked" Unchecked="chkbox_Checked"></CheckBox>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
                <DataGridTextColumn Header="ID" Binding="{Binding ID}"></DataGridTextColumn>
                <DataGridTextColumn Header="Name" Binding="{Binding Name}"></DataGridTextColumn>
                <DataGridTextColumn Header="Mobile no." Binding="{Binding Mobile1}"></DataGridTextColumn>
            </DataGrid.Columns>
        </DataGrid>
        ...
<StackPanel>

我正在使用StackPanel水平堆叠LogIn页面(未粘贴在上面的XAML中)和List以存储手机号码(如果选中了相应的复选框)。我还注意到List中的值保持不变,因为复选框的checked属性的值发生了变化。

如果我得到一个避免自动检查和取消选中DataGrid中复选框的解决方案,那将是非常好的。

谢谢!

2 个答案:

答案 0 :(得分:1)

据我所知,当 IsVirtualizing = true 时:

  • 不可见的 UI 元素仅在您滚动以取消隐藏时创建
  • 当您取消隐藏新行时,它会被创建、选中或取消选中,因此事件也会被触发

如果关闭虚拟化,性能将与数据网格中的项目数量成比例下降,因为即使它们不可见,也必须在 UI 中处理所有项目。

我在不关闭虚拟化的情况下的解决方法是只允许在您单击数据网格项目后的那一刻执行复选框选中/未选中事件,并在您开始滚动时禁用执行:

在您的 .xaml.cs 中:

bool _allowChckboxEvent = true;

private void CheckBox_Checked(object sender, RoutedEventArgs e)
{
   if (_allowChckboxEvent == false) return;
   //OnChecked stuff
}

private void CheckBox_Unchecked(object sender, RoutedEventArgs e)
{
   if (_allowChckboxEvent == false) return;
   //OnUnchecked stuff
}

//Enable checkbox events on left button click
private void MyDataGrid_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
   _allowChckboxEvent = true;
}

//Disable checkbox events when user starts scrolling the datagrid
private void MyDataGrid_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
   _allowChckboxEvent = false;
}

在您的 .xaml 中:

<DataGrid x:Name="MyDataGrid" ItemsSource="{Binding MyViewModel}" AutoGenerateColumns="False" PreviewMouseLeftButtonDown="MyDataGrid_PreviewMouseLeftButtonDown" ScrollViewer.ScrollChanged="MyDataGrid_ScrollChanged">
 <DataGrid.Columns>
  <DataGridTemplateColumn Header="IsVisibile">
   <DataGridTemplateColumn.CellTemplate>
    <DataTemplate>
     <CheckBox HorizontalAlignment="Center" IsChecked="{Binding IsVisible, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Checked="CheckBox_Checked" Unchecked="CheckBox_Unchecked"></CheckBox>
    </DataTemplate>
   </DataGridTemplateColumn.CellTemplate>
  </DataGridTemplateColumn>
 </DataGrid.Columns>
</DataGrid>

希望能帮到你。如果有人有更优雅的解决方案,我会很乐意学习:)

编辑:解决方案 2

在前面的示例中,您无法确定哪个事件将首先触发:选中/未选中或滚动更改。第二种解决方案效果更好。

在您的 .xaml.cs 中:

bool _allowChckboxEvent = true;

private void CheckBox_Checked(object sender, RoutedEventArgs e)
{
   if (_allowChckboxEvent == false) return;
   //OnChecked stuff
   _allowChckboxEvent = false; //checked/unchecked events are disabled right after youd stuff is done
}

private void CheckBox_Unchecked(object sender, RoutedEventArgs e)
{
   if (_allowChckboxEvent == false) return;
   //OnUnchecked stuff
   _allowChckboxEvent = false; //checked/unchecked events are disabled after your stuff is done
}

//Enable checkbox events right before you check/uncheck checkbox
private void CheckBox_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
   _allowChckboxEvent = true;
}

在您的 .xaml 中:

<DataGrid x:Name="MyDataGrid" ItemsSource="{Binding MyViewModel}" AutoGenerateColumns="False">
 <DataGrid.Columns>
  <DataGridTemplateColumn Header="IsVisibile">
   <DataGridTemplateColumn.CellTemplate>
    <DataTemplate>
     <CheckBox HorizontalAlignment="Center" IsChecked="{Binding IsVisible, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" PreviewMouseLeftButtonDown="CheckBox_PreviewMouseLeftButtonDown" Checked="CheckBox_Checked" Unchecked="CheckBox_Unchecked"></CheckBox>
    </DataTemplate>
   </DataGridTemplateColumn.CellTemplate>
  </DataGridTemplateColumn>
 </DataGrid.Columns>
</DataGrid>

答案 1 :(得分:0)

最好不要禁用虚拟化,因为您的应用程序完全没有响应。

你可以直接使用DataGridCheckBoxColumn,不需要繁重的DataGridTemplateColumn

<DataGridCheckBoxColumn Binding="{Binding NeedSendSms}"/>

然后在ViewModel中,您可以获得与NeedSendSms的所有联系人。

如果您仍想使用DataGridTemplateColumn,则需要绑定CheckBox的IsChecked属性以避免自动检查和取消选中。

<DataGridTemplateColumn>
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <CheckBox IsChecked="{Binding NeedSendSms}"/>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>