【问题标题】:Automatic checking and unchecking of checkboxes in WPF DataGrid on mouse scroll鼠标滚动时自动检查和取消选中 WPF DataGrid 中的复选框
【发布时间】:2016-11-27 04:43:40
【问题描述】:

我正在开发一个 WPF 应用程序,我需要在其中只向那些在 DataGrid 中选中的联系人发送 SMS。

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

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

  • DataGrid 中的 VirtualizingStackPanel.VirtualizationMode="Standard"
  • 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 水平堆叠登录页面(未粘贴在上述 XAML 中)和存储手机号码的列表。我还注意到,随着复选框的选中属性值的变化,列表中的值保持不变。

如果我能找到一个解决方案来避免自动选中和取消选中 DataGrid 中的复选框,那就太好了。

谢谢!

【问题讨论】:

    标签: c# wpf xaml checkbox datagrid


    【解决方案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>
    

    【讨论】:

      【解决方案2】:

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

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

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

      然后在 ViewModel 中你可以得到所有的联系人,NeedSendSms 为真。

      如果你还想使用DataGridTemplateColumn,那么你需要绑定CheckBox的IsChecked属性,避免自动勾选和取消勾选。

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

      【讨论】:

      • 我试过这个。但它不起作用。复选框仍然会在鼠标滚动时自动选中/取消选中。
      猜你喜欢
      • 1970-01-01
      • 2018-04-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-13
      • 1970-01-01
      • 2014-08-05
      • 1970-01-01
      相关资源
      最近更新 更多