开发者

Handling Checked differently depending on whether it's called from a mouse click or virtualization

I've got a WPF toolkit datagrid with virtualization turned on. Each row has a check box bound to a bool in the underlying model.

The check boxes (in addition to the data binding) also have Checked and Unchecked handl开发者_如何学编程ers (!) to allow checking multiple items at once if you've click one with multiple lines selected.

Here's the xaml:

<Controls:DataGrid ItemsSource="{Binding UnderlyingData}"
                   AutoGenerateColumns="False"
                   HeadersVisibility="Column">

  <Controls:DataGrid.Columns>
    <Controls:DataGridTemplateColumn Header="Use?" SortMemberPath="Use">
      <Controls:DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
          <CheckBox Style="{StaticResource DataGridCheckBoxStyle}" IsChecked="{Binding Spike}"
                    Checked="CheckBox_Checked" Unchecked="CheckBox_Unchecked" />
        </DataTemplate>
      </Controls:DataGridTemplateColumn.CellTemplate>
    </Controls:DataGridTemplateColumn>              
  </Controls:DataGrid.Columns>
</Controls:DataGrid>

And the Checked/Unchecked handlers:

private void CheckBox_Checked(object sender, RoutedEventArgs e)
{
    if (!processingMultipleRows)
    {
        UpdateAllSelected(e.OriginalSource as ToggleButton);
        e.Handled = true;
    }
}

private void CheckBox_Unchecked(object sender, RoutedEventArgs e)
{
    if (!processingMultipleRows)
    {
        UpdateAllSelected(e.OriginalSource as ToggleButton);
        e.Handled = true;
    }
}

private void UpdateAllSelected(ToggleButton checkBox)
{
    processingMultipleRows= true;
    var include = checkBox.IsChecked ?? false;
    tickBoxSelector.ApplyToAllSelected<RowViewModel>(checkBox, p => p.Use = include);
    ViewModel.ProcessUseStateChange();
    processingMultipleRows= false;
}

This code works in every way except one. ViewModel.ProcessUseStateChange() is fairly slow and is currently called once whenever you toggle one or more CheckBoxes. Which is fine, but it's also called once for each new line appearing in view when you scroll the datagrid, since virtualization means new rows have to be created and their Check state must be set.

Is there a cunning way to determine whether Checked is being called in response to a mouse click or an instantiation of a new row due to virtualization?


The solution I found in the end was to handle the Click event, rather than Checked/Unchecked, this simplified things hugely:

<Controls:DataGrid ItemsSource="{Binding UnderlyingData}"
                   AutoGenerateColumns="False"
                   HeadersVisibility="Column">

  <Controls:DataGrid.Columns>
    <Controls:DataGridTemplateColumn Header="Use?" SortMemberPath="Use">
      <Controls:DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
          <CheckBox Style="{StaticResource DataGridCheckBoxStyle}" IsChecked="{Binding Spike}"
                    Click="CheckBox_Clicked"/>
        </DataTemplate>
      </Controls:DataGridTemplateColumn.CellTemplate>
    </Controls:DataGridTemplateColumn>              
  </Controls:DataGrid.Columns>
</Controls:DataGrid>

and:

private void CheckBox_Clicked(object sender, RoutedEventArgs e)
{
    UpdateAllSelected(e.OriginalSource as ToggleButton);
    e.Handled = true;
}

private void UpdateAllSelected(ToggleButton checkBox)
{
    var include = checkBox.IsChecked ?? false;
    tickBoxSelector.ApplyToAllSelected<RowViewModel>(checkBox, p => p.Use = include);
    ViewModel.ProcessUseStateChange();
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜