Reputation: 75
I have a datagrid with the first column being a DataGridTemplateColumn of type Checkbox.
<DataGridTemplateColumn Header="Select">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate >
<CheckBox Name="chkSelectForMassRequest" Tag="{Binding AcctNum}" IsChecked="{Binding Path=IsSelected, UpdateSourceTrigger=PropertyChanged}" ClickMode="Press" Unchecked="chkSelectForMassRequest_Checked" Checked="chkSelectForMassRequest_Checked" ></CheckBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
The strange thing is that when the user checks a few checkboxes and then scrolls down through the data grid, some of the check marks disappear from the original checkboxes and reappear in the newly visible rows even though the user did not check them. My question is, how do I preserve the check marks in all rows regardless if the row is visible or not. And, how do I prevent check marks from moving around on scrolling?
Thanks in advance, Mark
Upvotes: 2
Views: 2583
Reputation: 3
If you want to keep the DataGrid virtualization while also fixing the issue, you can add an event to the DataGrid's scroll event handler which deselects the selected cells and items during scrolling and reselects them after scrolling as stopped for a duration. An example follows below.
You can add the following event to the DataGrid's PreviewMouseWheel event handler:
private DispatcherTimer scrollFinishTimer;
private List<object> previouslySelectedItems = new List<object>();
private List<DataGridCellInfo> previouseSelectedCells = new List<DataGridCellInfo>();
private DataGrid grid;
private void grid_PreviewMouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e)
{
// When scrolling starts
if (!scrollFinishTimer.IsEnabled)
{
// Save the currently selected items
previouslySelectedItems.Clear();
foreach (var item in grid.SelectedItems)
{
previouslySelectedItems.Add(item);
}
if (grid.SelectionUnit != DataGridSelectionUnit.FullRow)
{
foreach(var item in grid.SelectedCells)
{
previouseSelectedCells.Add(item);
}
}
grid.UnselectAllCells();
grid.UnselectAll();
}
// Reset the timer every time the event is triggered
scrollFinishTimer.Stop();
scrollFinishTimer.Start();
}
With grid defined either in the code behind or in your custom grid class. The scrollFinishTimer should be defined like so
scrollFinishTimer = new DispatcherTimer
{
Interval = TimeSpan.FromMilliseconds(200) // Or whatever time you prefer.
};
scrollFinishTimer.Tick += ScrollFinishTimer_Tick;
with ScrollFinishTimer_Tick as:
private void ScrollFinishTimer_Tick(object sender, EventArgs e)
{
// When the timer ticks, consider scrolling finished.
scrollFinishTimer.Stop();
// Reselect the previously selected items and cells if they're still valid
foreach (var item in previouslySelectedItems)
{
if (grid.Items.Contains(item))
{
grid.SelectedItems.Add(item);
}
}
if (grid.SelectionUnit != DataGridSelectionUnit.FullRow)
{
foreach (var cell in previouseSelectedCells)
{
if (!grid.SelectedCells.Contains(cell))
{
grid.SelectedCells.Add(cell);
}
}
}
}
Upvotes: 0
Reputation: 1
If you have checkbox in a row alignment, you could try add EnableColumnVirtualization="False" EnableRowVirtualization="False" in the XAML that declares the DataGrid
ex.
DataGrid x:Name="here" EnableColumnVirtualization="False" EnableRowVirtualization="False"
Upvotes: 0
Reputation: 151
I was able to solve it with Mode='TwoWay' and UpdateSourceProtepry='PropertyChange'
<DataTemplate>
<CheckBox IsChecked="{Binding Yes,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" RenderTransformOrigin="0.5,0.5" HorizontalAlignment="Center"/>
</DataTemplate>
Upvotes: 2
Reputation: 65
I tried changing the VirtualizationMode also but that didn't work for me. I just turned off virtualization entirely and that's what got rid of the problem entirely.
EnableColumnVirtualization="False" and EnableRowVirtualization="False"
Upvotes: 2
Reputation: 20471
This is because the DataGrid has virtualization switched on by default which is conflicting with your UpdateSourceTrigger directive within your Binding.
Either remove the UpdateSourceTrigger and make the binding TwoWay, or add 'VirtualizingStackPanel.VirtualizationMode="Standard"' in the XAML that declares the DataGrid
Upvotes: 0