I am working on a page with two tables: one to show all the items, and one to show only the selected items. An item can added to/removed from the selected list by a checkbox in either table that is bound to a boolean in the view models. The view models notify other entities in the page that an item has been selected or deselected by way of a delegate that is passed in on construction of the view model:
public bool ItemViewModel.Selected { get { return this.selected; } set { if (this.itemSelectedChangedHandler != null && value != this.selected) { this.selected = value; this.itemSelectedChangedHandler(this.item, this.selected); } } }
When an item is selected/deselected, the selected list will update by hiding non-selected items and showing selected items. It will also call a method to set the selected value of the view model without invoking the itemSelectedChangedHandler:
private void PageViewModel.UpdateSelectedItemsTable() { foreach (var row in this.selectedItemsTable.Rows) { var itemViewModel = row.ListObject as ItemViewModel;
if (this.dataModule.SelectedItems.Contains(itemViewModel.Item)) { itemViewModel.Select(true); itemViewModel.UpdateChildren(); row.ExpandAll(); row.Hidden = false; } else { itemViewModel.Select(false); row.CollapseAll(); row.Hidden = true; } }
}
public void ItemViewModel.Select(bool selected) { if (this.selected != selected) { this.selected = selected; this.OnPropertyChanged(nameof(this.Selected)); } }
I can successfully select and deselect items from the table of all items (which has a different view model but ends up calling the same UpdateSelectedItemsTable), however, when I try to deselect an item from the selected table, I can deselect the first item, but subsequent items will not enter into their set accessors when I click their checkbox. To make debugging even more confusing, if I have a breakpoint on the set accessor from the beginning, before I select or deselect any items, I can successfully deselect all items by clicking their checkbox in the selected items table. I have no idea why the same code would have different outcomes when I step through it and when I don't.
Any thoughts or suggestions would be appreciated at this point!
Thank you!
Hello Tanner,
Your application’s logic is quite complex, and I am not able to reproduce it at my side. So can you please try to isolate this behavior in a small sample project and send it to me. This will allow me to investigate this behavior, and to try to find the root of this issue. Please let me know also, which the exact version of Infragistics for Windows Forms you are using is.
Looking forward to your reply and sample provided.
Hi Mike,
Thank you for the reply. I am trying to isolate this behavior in a small project, but it is eluding me. Based on the behavior, do you have any initial thoughts on what might be causing it? I was thinking that having a view model initiate a sequence to update its own properties might cause the binding to break, but it works in the isolated sample project, so I am still searching for the culprit. I think I have to take everything out of my main project and slowly add stuff in until it breaks.
I do not handle the InitializeRow event. I call for validation in a AfterCellUpdate event handler.
I have narrowed the issue down to a single line of code that gets fired when all pages have completed their validation:
EventAggregator.GetEvent<UpdateRunValidationEvent>().Publish(new UpdateRunValidationEventArgs(allIsValid));
Hopefully you are familiar with Microsoft Prism, but if not, its a loosely-coupled event framework.
If I comment the above line out, everything works as expected. If I just comment the code out of the event handler, the checkboxes still freeze, which indicates the problem has something to do with just the event aggregator. If I put a breakpoint in the event handler, I can successfully uncheck all the boxes after stepping out of the breakpoint each time. I have put the exact same code into my isolated test app, but it works correctly without the breakpoint. So maybe something is going on with threading? Is the ultragrid multithreaded?
Hi Tanner,
I am not familiar with Prism, but I think you are probably on to something with threading. The UltraWinGrid not mullit-threaded, nor is the DotNet BindingManager or any other DotNet controls that I am aware of. So If Prism or your code is doing anything on another to the grid or the data source on another thread, then that would certainly explain the behavior you are getting.
I figured out the issue, although I am still unclear why it was happening.
In the event handler for when all page validations had completed, I was calling the method of a background engine to get its status. This wouldn't throw an error to me, but if I didn't call that method, everything would work. So even though that method was completely unrelated to the underlying data of the grid, because it was accessing something on a different thread I guess that ended up disrupting the table? I'm still at a loss but I'm glad this silly error is resolved.
If your background thread is accessing anything on the UI thread (like the grid or the grid data source) in any way, then that's a problem. Because the grid or the data source might be accessed by the UI Thread at any time and you have no control over that.
It definitely doesn't access anything on the UI thread, my code only has references to it, it doesn't know about or modify my data. It is simply an engine we are using from another group but it was developed years ago, there is little documentation, and the source code is hard to find, so at this point it is pretty much a black box.
Unfortunately there was no strong resolution as to why this was happening, but at least I was able to figure out what caused it. Thank you for all your time and help!