How to find out when DevExpress XtraGrid row visibility changes? - winforms

Is there easy way to find out when DevExpress XtraGrid rows visibility changes?
I am using WinForms DevExpress XtraGrid. I need to know which rows are visible. I can find out which rows are visible at the moment, but I do not want to calculate it every time. So I calculate it when needed, store it, and invalidate if operation that can change visibility occurs. Which is scroll, resizing control, sorting, grouping, expanding or collapsing group, filter change, add or remove of item in data source, or change to item in data source when grid is sorted or filtered.
As you can see it became pretty ugly. Is there easier way to notice changes of visibility of rows? Is there event when row changes visibility or moves for any reason?

Unfortunately there is no event able to handle behaviour you've described - you have to handle number of events (sorting,grouping, etc.) and call function recalculating set of visible rows in each of them.
Regards,
Maciej Nowicki

Related

WPF DataGrid loses virtualization when sorted by specific columns

I am using a WPF DataGrid that is bound to a custom ItemsSource that implements IList (and NOT IEnumerable). The custom ItemsSource performs data virtualization and only loads pages of items as needed. MyDataGrid actually inherits from DataGrid and overrides the handling of the DataGrid sort methods so that I can maintain data virtualization while sorting. I have UI Virtualization turned on for MyDataGrid.
When I run the application, MyDataGrid displays just fine, tells me I have roughly 20,000 items, and only asks my ItemsSource for the first 20 or so items. I then can click on column headers to sort various columns and again my ItemsSource only has to reload the first page of 40 items because MyDataGrid has asked to refresh only the first 20 or so.
BUT, when I click on my Last Name column to sort, MyDataGrid loses its UI Virtualization and asks my ItemsSource to load every single item even though it only needs the first 20 or so. I can watch as it asks for every single item by index (this[0]).
I've tried researching ICollectionView, UI Virtualization, and Data Virtualization and the only thing that I've read that seems it may apply is regarding multiple row selection (at DataGrid row request patterns with data virtualization I've set MyDataGrid's SelectionMode to Single so this shouldn't apply.
Another hint may be that, prior to sorting by Last Name, the first item in MyDataGrid has a last name that starts with the letter V (very late in the alphabet), and that I can actually sort the list in Descending order by last name without losing virtualization. The same thing happens with my Title column which has a first item that starts with the letter S. I don't have the problem with any of the other columns.
Any ideas?
FIGURED IT OUT!!! Looking through the call stack, it appeared that the problem was happening during the MeasureOverride of the VirtualizingStackPanel and I noticed it was calling the SyncUniformSizeFlags method. So I then went into the default style for the DataGrid and set the RowHeight to a fixed amount and it no longer causes the problem.
So, it appears that the DataGrid can lose its virtualization when a fixed RowHeight is not set. Still don't know why opting to sort in ascending order by Last Name or Title caused it to want to resync the row heights, but I can work around that one.

ScrollBar on DataGrid keeps jumping back to the top

I am working with a WPF MVVM solution where I have a grid that is being updated multiple times every second. I need to allow the user the ability to scroll halfway down the grid and to remain there in between grid data updates. Right now if I scroll down the grid, the scrollbar position will jump back to the top as soon as the next time the grid's data is updated.
How can I accomplish keeping the x position of my scrollbar in its current location even when updates are processed. Please let me know.
Are you replacing/resetting the collection the datagrid is bound to in your updates or are you modifying the collection? I believe the grid will reset if you do something like myCollection = UpdatedCollection as opposed to modifying your collection using myCollection.Add(x) and myCollection.Remove(x)
<ListBox ScrollViewer.VerticalScrollBarVisibility="Visible"
ScrollViewer.CanContentScroll="False"/>
will should resolve this problem.
The reason is normally that the ListView always goes to the last selected element.
Also you need to make sure that the list is being populated by binding.

WPF - Need an event for when VirtualizingStackPanel creates Items for ListView

Is there any way to tell when the containers are finished being made for a ListView?
A detailed explanation of what I've done so far
I have a ListView control that has a DataTemplate in one of its columns that contains a CheckBox Control.. I've figured out how to access the CheckBox dynamically using the object that the ListView is bound to.
ListViewItem lItem = (ListViewItem)ListView.ItemContainerGenerator.ContainerFromItem(trackToHandle);
CheckBox checkBoxToHandle = FindChild<CheckBox>(lItem, "CheckBox");
The problem is that the CheckBoxes "reset" (become unchecked) whenever I scroll too far or whenever I sort the columns.
I figured out this was because the VirtualizingStackPanel was only spitting out containers for those ListViewItems that were visible (or almost visible)..
And because the CheckBox is inside a DataTemplate that is defined in the XAML it gets thrown away everytime it goes out of view or when the list is sorted.
I got around this by creating a separate list of CheckBoxes and using the actual CheckBoxes "click" event to change the state of the corresponding CheckBox in my list.. then made a little method to go change the state of all the visible CheckBoxes whenever the user scrolls... as a result it appears like it should have in the first place.
Except when I sort the columns.
I tried making it re-do the CheckBoxes (like before) right after it'd sorted a column but it didn't work.
My best guess is that it doesn't immediately make the containers after I sort..
Is there any way to tell when the containers are finished being made for a ListView?
If you bind your checkboxes IsChecked property to a boolean property on your data context, then you will not have this issue.
The whole purpose of the VirtualizingStackPanel is reduce memory usage by not creating ListItem's unless needed.
In effect, you need to move the data side of the checkbox away from the control.

How to Disable Tab functionality inside a grid in WPF

My requirement is rather a tricky one (it seems to me).
I will explain the scenario.
I have a DataGrid. In the DataGrid, I have two columns in which I have a grid in every cell of these two columns, inside of which, there are two comboboxes - the purpose being to switch the visibility based on some conditions.
When we select a value in the combobox, the combobox itself, plus some other controls in some other columns will get disabled (requirement of the pjt). Now there is also, another requirement like, Tab should not be allowed in the cell which has disabled controls - say disabled combobox.
We are setting the controls as Enabled or Disabled based on a selected value from the combobox. So, since we are applying the disabling property on the control level, and the IsTabStop property is on the cell level, I am not able to restrict Tabbing in the cells having disabled control.
Any thoughts?
Don't use a DataGrid.
DataGrid's are awesome for read-only stuff, but they seem to suck for doing any kind of interesting editing. After well over a week of fighting with it, I've given up on it.
Right now I'm looking for a replacement, which may end up just being a scrollable stack panel with manually added controls.
WPF: Is there a "ListBox" without the ability to select items?

Master/Detail UI Best Practices?

We have a WPF app that has a master/detail window, both being WPF Datagrids. When you select a row in the upper datagrid, the details are shown in the lower datagrid. I was wondering if there are any best practices from a UI perspective on how to deal with things such as:
When the window first opens, no datarow is selected in the upper datagrid, and so no data can be displayed in the lower grid. Is this normal? Or is there typically an initial (top) row selected in the upper datagrid?
When a row is selected and then deleted - does another row become the selected row? Or are you going to go to a no row selected state?
If multiple rows can be selected, when happens in the lower datagrid? Show the last one selected? Or if delete is selected for these multiple objects, where is focus set? Or what row is selection?
I know there are a lot of different ways these things might be handled depending on how the app is written, but I wondered if there is some standard best practices? Or if there is some default operations for how the WPF datagrid might handle these cases?
thanks!
Bill
I think the first two considerations can come down to preference. I'd prefer to have the first row selected and its details shown when the window first opens -- this tells me, as a user, how this window works. Not sure how it works in WPF, but in Windows Forms, the datagridview pre-selected the top row by default (and getting it to stop doing that requires tricks).
When I remove a row, I personally prefer to go to a "no row selected" state, but I don't have much to back that up with in terms of "this is why you should do it". I just like seeing the empty "detail" view and lack of selection as confirmation that I did successfully remove the selected row.
The last point, however, I think is more clear-cut. If you have a master/detail relationship in views, you should not allow multiple selection. If you need the user to be able to perform actions on multiple rows of the master gridview, you can add some checkboxes to the rows to allow the user to pick a subset of rows to act on. But for the purposes of showing details, only one row must be selected at a time.

Resources