WPF keeping a TreeView list sorted - wpf

I have a node on a TreeView that I populate manually and want to keep sorted. Through user interaction the headers on the TreeViewItem's may change and they should move to the appropriate spot in the list.
I iterate through a foreach creating numerous TreeViewItem's and adding them to a parent node. It is all of the children that need to be sorted. I then add a SortDescription as follows.
tviParent.Items.SortDescriptions.Add(new SortDescription("Header", ListSortDirection.Ascending));
This sorts the intial list, but if I change the header for one of the tree view items after it is displayed the item does not sort again. The header text changes, but the items position in the list remains the same.
Is there something I am missing?
I have tried clearning the list and repopulating it, which will work, however it causes some isues in my program as I have a lot of logic for when the selected item is changed and since one of the tree view items in the list that I am clearing is selected it invokes all of this logic when I clear the list and then again when I programmatically reselect the item after rebuilding the list.

The items collection will have to be refreshed upon any change to its property
try the following code after the header edit ....
tviParent.Items.Refresh();
if the code above does not work then try code below after each edit ...
tviParent.Items.SortDescriptions.Clear()
tviParent.Items.SortDescriptions.Add(new SortDescription("Header", ListSortDirection.Ascending));

If you set
yourCollectionView.IsLiveSorting = true;
then it will update automatically.
Also to get this to work recusively put this into a converter like here: https://stackoverflow.com/a/5730402/364429

Related

Event to fire after a System Windows Form element has been updated

I have a Windows form with a series of list boxes
The contents of subsequent lists change based on choices in earlier ones
All the boxes are bound to a BindingList with OnListChanged enabled
I use this to retain user-specified 'checked' items when elements are added or removed
However, I note that if I add an item to the list, it appears to update the UI only after all the other events have been fired
I've looked at the events I would expect to fire on the CheckedListBox, and in the related ViewModel, in order to catch the one which adds an item to the list, but so far without success
Can someone please advise me which event would allow me to call my 'CheckBoxes' method after the UI has been updated, otherwise they all get set to blank again until the form is closed and opened
private void OnPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
// I've removed the debug statements, but this event when the bound list updates is fired before the UI updates
}
private void teams_checked_list_box_SelectedIndexChanged(object sender, EventArgs e)
{
// same with this event, and the other events like SizeChanged
}
EDITED: On reflection, I realise that the problem occurs because I am not setting the true / false checked flag in the binding, because I couldn't figure out how to do it. If someone could point me in the right direction? Code currently looks like this:
teams_checked_list_box.DataSource = Globals.ThisAddIn.TFSTeamsViewModel.ListOfTeamsFromVM.value;
teams_checked_list_box.DisplayMember = "name";
So basically I am only updating the item name, and the check flag is handled on a later pass
How are you adding items to your list? Are you re-binding the listbox? There are basically two ways you can do this depending on your method of adding items:
If you are re-binding, capture the event BEFORE the item is added. Loop through the CheckedItems property of your list box. Save the values. Add your item. Loop through the NEW values and recheck.
OR
When the user checks the item in the listbox, capture that using the ItemChecked event and then store the value of the item somewhere. (Variable, hidden textbox -- ugly, but it works -- etc.) If you are only adding items to the BOTTOM of your list, you can store the index of the item. If you are re-sorting your list, you'll need to store a unique id to reference the item. (Note: you will also need to REMOVE the checked items from your stored value if the user UN-checks an item in your listbox.) Then, after you add your items to the listbox, loop back through and set the checked value on the appropriate listbox items.

Reset a ComboBox

I have a view that contains several ComboBox elements. For some reason old data remains from the previous time the view was opened and I would like to reset the combobox elements in the view every time it is opened. Is there a function that could that for me? I want it to be exactly how it is as if I rendered it the first time with the initial items. Would using setSelectedItem(vItem), setSelectedItemId(vItem), setSelectedKey(sKey), setShowSecondaryValues() help? If so, what do these keywords mean (selectedItem, selectedItemID, selectedKey, secondaryValues)?
Unfortunately you do not provide an example. Normally you bind your UI controls against a model, e.g. JSONModel. In this case the items of your ComboBox controls would be taken from the corresponding model. However, you can use method removeAllItems to achieve the desired behaviour.
UPDATE: Obviously the controls are bound and only the selection should be cleared.
Use setSelectedItem with value null to clear the selection. You could also use the binding to set the selected item automatically by using the selectedKey attribute, see example.

Compatible value's position in an editable ComboBox

I have a ComboBox implemented with an auto-completion system. My ComboBox contains more than 100 items. When users are typing text in, the auto-completion system opens the dropdown list and highlights the most relevant item. Moreover, when the dropdown list is expanded, all items are available (no filters). But the most relevant item is always at the bottom of the dropdown list.
I would like it to be in the middle, if possible. One item can have the same reference but another type than another one, that's why I need to see most of them in my dropdown by placing them in the middle.
Any idea ? It's not really important but kind of useful for them. Thanks !
Update :
Here's my ComboBox with the open dropdown. Sorry about that, I had to blur its elements. As you can see, the user starts writting the reference in the ComboBox. The autocompletion works fine, but the corresponding item is found at the end of the dropdown list (in the red frame), almost out of bounds.
I wish it would be highlighted in the middle of my dropdown list instead of so far below.
Your item search may work well, but your list isn't visually filtered, which means it's size always remains the same.
It's scrolled into view, by the wpf system, but still displaying all other items around the relevant one. The reason why it's at the bottom is because wpf Scrollviewer just finished scrolling the item into view and sees no need to scroll it further into the middle.
You could use the CollectionViewSource class. Why ?
It's simple to use, will keep your viewmodel data as it is, and you would have your relevant completion item at the top. It can be obtained by GetDefaultView(..)
Let's say you have a viewmodel flag "IsHidden", stating that it's content does not match the user input:
ICollectionView cv= CollectionViewSource.GetDefaultView(myComboBox.ItemsSource);
// switch filter on
cv.Filter = obj => (obj as myViewModel).IsHidden == false;
// switch off
cv.Filter = null

Listbox doesn't update after adding new items to it

I have a list box that is bound to an Observable Collection , when I the user add any new items to it it doesn't update itself until the app is closed and opened again.
(I serializes the content of the item source of this list and store it in Isolated Storage)
The only possible solution until now is to set the item source after adding the item in every method that allow the user to add any item but this isn't possible while adding from other pages as I can't access UI elements directly. Any help ?
I solved it ! In the Deserialize method I was pointing to another list (the one that has the result to Deserialization) and that damaged the binding.

ComboBox selection not reset to top of dropdown list (items) in javafx 2.2

I have a Source ComboBox to populate source fields (25-30 items) shown below in first page
"A"
"B"
...
"Z"
I have selected last item from ComboBox as shown below
"Z"
and when traversing to the next page after saving, i need to make the source combo selection blank, so i have return the below code to reset the Source combobox to point to first item (to reset the display to start from top of dropdown list for user selection)
// my first value in source List is empty space - “”
sourceComboBox.setValue("");
even if you use below code snippets like
sourceComboBox.getSelectionModel().selectFirst();
sourceComboBox.getItems().clear();
sourceComboBox.getSelectionModel().clearAndSelect(0);
but when i click open the combobox dropdown it still shows dropdown display from bottom as shown below
...
"X"
"Y"
"Z"
I am unable to post images for representing combobox values, so has put in above examples.
This looks like a graphics bug to me or am I doing something wrong?
I have seen similar issue reported in below question but no work around suggested so far
Combobox clearing value issue
If you want to simply "reset" the combo box, I think all you have to do is set the value to null, like so:
sourceComboBox.setValue(null);
I ran into nearly the exact same situation and came across your question while looking for a solution. Fortunately, I came up with a workaround that forces the ComboBoxes to reset. When you reset the data on your pane, instead of doing something like:
sourceComboBox.getSelectionModel().clearSelection();
sourceComboBox.getItems.clear();
do something like this...
parentNode.getChildren().remove(sourceComboBox);
sourceComboBox= new ComboBox(); // do whatever else you need to format your ComboBox
parentNode.add(sourceComboBox);
You'll also need to do a setItems() again on your ComboBox so the new one will be populated. This is not an ideal solution but it seems to be working as I expect the provided clearSelection() method would.
Below is the code you're looking for. It will reset it to whatever index you give in within the parenthesis.
sourceComboBox.setSelectedIndex(0);
Goodluck
Most of the things were giving me an error when I tried them. What worked best for me was to use this
comboBox.getSelectionModel.clearSelection();
This will essentially set the value of your ComboBox to null. Because of this, if you are referring to the value of the ComboBox in another place, it becomes important to check for whether the value of the ComboBox is null using this
if(comboBox.getValue() != null)
//Code segment here
The ComboBox control has not a method like scrollTo(index) of the ListView. So it seems hard to workaround that behavior. You can issue a feature request at JavaFX Jira.

Resources