I have a datagrid to which I bind some items. I only allow selecting rows (single item) on this grid.
This grid has a DataGridCheckBoxColumn and a SelectionChanged event.
The problem is that when the user presses a checkbox, it also selects the row (and triggers the SelectionChanged event). This is not the behaviour I would like.
Is there a way I can either prevent the SelectionChanged event from triggering when pressing the checkbox OR detect if was the checkbox column that was pressed in the selectionchanged event?
Thanks!
What about adding a Mouse_Click event on DataGrid row and if it's original source is Checkbox then set e.handled = true otherwise go ahead.
Related
I am using checkbox in an itemtemplate column in a Silverlight 5 DataGrid.
I am facing a strange problem with it. When I select more than one checkbox and then scroll the grid up and down, the selection shifts to some other checkbox.
I fixed this problem in my code. I did handling within the LoadingRow and UnloadingRow events of the grid.
As soon as a row is loaded, we need to look for the condition on the basis of which we want to keep the check-box checked or unchecked. But as soon as you set the IsChecked property, Checked or UnChecked event of the check-box will get fired.
In this scenario we can unregister the Checked and UnChecked events of the check-box if we have any, set the IsChecked property. After setting this, again register the events.
Below is the code for your help.
Add LoadingRow and UnloadingRow events to your grid.
... LoadingRow="DGUserList_RowLoadUnload" UnloadingRow="DGUserList_RowLoadUnload">
In your code behind file:
private void DGUserList_RowLoadUnload(object sender, DataGridRowEventArgs e)
{
DataGridRow row = e.Row;
CheckBox cbox = (CheckBox)this.dgUserList.Columns[0].GetCellContent(row);
this.UpdateHookedEventsForCheckBox(cbox, false);
cbox.IsChecked = true; // Here put your condition for check/uncheck
this.UpdateHookedEventsForCheckBox(cbox, true);
}
private void UpdateHookedEventsForCheckBox(CheckBox chkBox, bool register)
{
if (register)
{
chkBox.Checked += this.CheckBox_Checked;
chkBox.Unchecked += this.CheckBox_Unchecked;
}
else
{
chkBox.Checked -= this.CheckBox_Checked;
chkBox.Unchecked -= this.CheckBox_Unchecked;
}
}
This way I need not bother about putting some hake code in my Checked and UnChecked events.
This is a known behaviour since Silverlight is re-using its graphical resources in the DataGrid. There's a discussion about it in this Silverlight thread.
It seems one way to fix it is to databind the IsSelected property:
My solution at that time was to add a new property in my data source:
IsSelected, and to bind the checkbox to that value.
You have more additional info in this thread, where Microsoft answers:
This is not a bug. What happens when you scroll around in the
DataGrid is the same checkboxes are being used for new data because
the DataGrid recycles the visuals. When your new data has different
values, the check will change through the Binding and you'll receive
the event. What you can do to get this scenario to work is to listen
to LoadingRow which is raised when a row comes into view. In there,
you can call column.GetCellContents to get the contents of the cell.
This will give you the CheckBox, and you can attach to CheckChanged at
this time. If you do this, you need to do something similar and
listen to UnloadingRow so you can detach the eventhandler when the
checkbox is scrolled out of view.
Is there an event that gets fired when one clicks the ColumnHeader of a Datagrid to trigger a sort on that column ?
Thanks in advance
DataGridColumnHeader is a control itself so you should be able to assign an handler to its MouseLeftButtonDown event programatically.
I am new in WPF and I have a question about the DataGrid, how could I get the item at the mouse position when I perform a Double Click on DataGrid?
You can subscribe to the DoubleClick event using a Style and an EventSetter, for rows use the RowStyle, for specific cells the CellStyle.
In the handler you can then cast the sender to DataGridRow or DataGridCell respectively.
([Example with rows])
I have a MainWindow with 3 main buttons at the top and below a MainUserControl.
In the MainUserControl I have at top 3 UserControls with ButtonBars
and at the bottom a DataGrid.
When I enter data in a DataGridCell and I click into another cell a property change is fired in my ViewModel bound to the DataGrid.
When I enter data... and I click on one of the 3 main buttons again a property change is fired because of Lost Focus event.
When I ... and I click on one of the buttons in the ButtonBar in the UserControl no property change is fired because there seem to be no Lost Focus event.
How can I fix that?
FocusManager.IsFocusScope="False" on the UserControl or other elements like Menu solved the problem and my property changes are raised now in the model :)
If you change your binding to to set UpdateSourceTrigger=PropertyChanged then you will not need to rely on the LostFocus to do a property update.
I am building an issue tracking system that uses Silverlight. I use DataGrids to display the issue lists, set the selected index to -1 so that no row appears selected and then use the selection change event to popup an issue details window for the particular selected issue.
When I try to refresh the DataGrid by rebinding it to its ItemsSource, I disable the SelectionChanged event, rebind the DataGrid to its ItemsSource, set the SelectedIndex to -1 and then enable the SelectionChanged event again. However, no matter how late I leave the re-enabling of the SelectionChanged event (even until after the DataGrid_Loaded event), a SelectionChanged event is fired and the issue details window pops up.
Is there a better way to refresh the data in a DataGrid that won't cause the SelectedIndex to change? If not, is there a way of telling which events are caused by a programmatic index change and not a human interaction?
(Also up for discussion, is this the best control for the job? I need to display multiple fields per row, such as the issue title, assigned user, requested by user, status, etc.)
Thanks in advance.
I have had a similar issue in the past with the comctl32 ListView control's selection events: Programmatic selection cause selection change events to be raised.
My workaround for this issue is to have a per-grid/list counter variable that lets the event handler know if it should care about the selection event or not. The code would go something like:
int issueList_ProgrammaticEventCount_Selection = 0;
void refreshIssueList()
{
++issueList_ProgrammaticEventCount_Selection;
issueList.ItemsSource = ...;
}
void issueList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (issueList_ProgrammaticEventCount_Selection > 0)
{
--issueList_ProgrammaticEventCount_Selection;
return;
}
showIssueDetails();
}