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

xxslljrj  于 2023-03-09  发布在  其他
关注(0)|答案(2)|浏览(335)

我正在开发一个WPF应用程序,在该应用程序中,我只需要向那些在DataGrid中选中的联系人发送SMS。
在数据网格中选中所需的联系人后,我在向下/向上滚动时遇到问题。数据网格中复选框的选中属性随机更改。
我遇到了一些建议添加以下属性的解决方案:

  • 虚拟化堆栈面板。数据网格中的虚拟化模式="标准"
  • VirtualizingStackPanel. IsVirtualizing ="True"在DataGrid中(当我将其设置为False时,应用程序变得完全没有响应)
  • 复选框绑定中的UpdateSourceTrigger ="属性已更改"
  • 在数据网格中启用行虚拟化="True"
  • 在数据网格中启用列虚拟化="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中的复选框,那就太好了。
谢谢你!

rjjhvcjd

rjjhvcjd1#

根据我的理解,当IsVirtualizing = true时:

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

如果您关闭虚拟化,性能将与数据网格中的项目数量成比例下降,因为所有项目都必须在UI中处理,即使它们不可见。
我在不关闭虚拟化的情况下的解决方案是,仅允许在您单击datagrid项之后执行复选框选中/未选中的事件,并在您开始滚动时禁用执行:
在您的. 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**

在前面的示例中,您无法确定将首先触发哪个事件:选中/未选中或scrollchanged。第二个解决方案效果更好。
在您的. 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>
kkbh8khc

kkbh8khc2#

最好不要禁用虚拟化,因为您的应用程序将完全没有响应。
您可以直接使用DataGridCheckBoxColumn,而无需使用繁重的DataGridTemplateColumn

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

那么在ViewModel中,您可以获得所有联系人,NeedSendSms为true。
如果您仍然希望使用DataGridTemplateColumn,则需要绑定CheckBox的IsChecked属性,以避免自动选中和取消选中。

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

相关问题