I have the following scenario:
User enters values in a form and submits
The submit methods calls a service passing the form related object as a parameter
The object is persisted in the db
The object gets assigned a new ID and gets returned to the calling method
The object is add to a collection in the submit method
I have an expander control that is bound to the collection using an item list and inside each list is a sub list.
What is the best practice for refreshing the view to show the updated object. What I was doing to refresh the collection was the following:
ObservableCollection<ProjectDto> projects = new ObservableCollection<ProjectDto>();
Projects.ForEach(projects.Add);
Projects.Clear();
projects.ForEach(Projects.Add);
This makes the expander collapse as I think it is being bound to a new collection.
What is the relationship between projects (little p) and Projects (capital P) - why two lists?
What does your binding look like?
EDIT
Let's assume for discussion that Projects is an ObservableCollection, and is what is bound to your UI, and that projects is either a temporary, domain model, or backend list that you use to assemble and prepare (sort, validate, etc.) DTOs for presentation. In this case, projects can just be a List, and you can every time you do Projects = new ObservableCollection(projects) your bound UI items collection should refresh.
Berryl
Related
I've got a ListBox and a DataGrid where the ListBox shows a subset of the list of the DataGrid. I created the two lists that the control's are bound to separately, however both control's SelectedItem are bound to the same property in the view model. I need to have both controls select the same item when the user clicks on either control's items unless the user clicks on the DataGrid on an item that is not in the ListBox's subset (then the ListBox should not have anything selected).
I'm guessing since the lists were created separately they are not the same object so is there a way to provide some sort of comparison logic to the controls to select an item that essentially has the same name (or value or some sort of criteria)? If that doesn't exist then I guess the best way would be to create the subset list of objects from the exact same objects in the superset.
I'm guessing since the lists were created separately they are not the same object
You could add the very same object to two different collections, e.g.:
YourType obj = new YourType();
list1.Add(obj);
list2.Add(obj);
This should solve your issue.
You could also override the Equals method of YourType as suggested in the comments but you shouldn't have to if both collections references the same objects, which they should since the second is a subset of the first.
I have an app with a great many dropdown lists that should remain synchronised between windows. I.e. if a user adds e.g. a new Department, all open forms with Department dropdowns must have the new department as well.
My first thoughts for this is a List Model, from which view models pull their lists. All are ObservableCollections, so the view models subscribe to the list model, wich subscribes to the viewmodels for list changes, and incorporates them.
Or am I building a house of spaghetti here?
Another requirement (these aren't mine) is that list changes by one user, common with other users only through the database, must propagate to other users. I can only think of a broadcast message sent by the list model that is the origin of the change.
Your solution seems solid. I'd have a MainWindowViewModel with your ObservableCollection<Department>. When you create a new window, you can pass the reference to the ObservableCollection from the MainWindowViewModel to the constructor of your new window's view model. This way, adding new departments will automatically sync to every windows regardless of where it's added.
I have a small gui with a listbox. The listbox is bound to a collection. The user can edit an item in the collection using an "Edit" window.
The Edit window is bound to the selected object in the listbox. One of the validations I need to perform is to make sure the user does not enter a name for an item which has already been used (meaning it can't be used by any of the other objects in the listbox).
Is there a good way to do this with WPF validation?
The item you are validating must provide reference to a parent object (collection).
When you have parent collection, the rest is simple, and I think, got nothing to do with WPF.
Take a look at the Enforcing parent-child relationship in C# and .Net
I'm currently building an application that utilizes a ComboBox to allow the user to select from a dynamic list of String objects contained within a BindingList object. However, the BindingList is a member of a child class belonging to the main class, which appears to be causing some issues.
When the ComboBox's data source is set initially within the main class via:
this.comboBox.DataSource = this.childClass.dataList;
the contents of the ComboBox appear as expected. However, when the contents of the list changes, the contents of the ComboBox are not updated.
If the BindingList object belongs to the main class, the ComboBox updates without any issues. It would appear that the parent class is not receiving the events that signal that the list has been updated.
Any ideas?
After looking at a similar question I asked (and answered) last year:
Adding/Removing COM Ports from a ComboBox in C#
, it seems I've (re)discovered the solution. The problem was with how the strings were being added to the data source. Because the list was being augmented in another thread, there was an issue with the ComboBox control being updated. By utilizing a delegate and the Invoke() method, the contents of the ComboBox are now updated as expected.
Basically, I'm wondering how it is actually efficient here.
Sample code:
void GetItems()
{
foreach (var item in items)
myObservableCollection.Add(item);
}
Won't this fire off the CollectionChanged event every time causing the UI to have to refresh everytime? Or does it do it so that it waits til the GetItems function is done?
Basically, it seems that WPF handles it very well, and I'm wondering how they did that.
Optimizing Performance: Data Binding provides some background on how data bindings are resolved, including the performance implications of different items sources. Take a look at the Binding to an ItemsSource section.
Consider a scenario in which you have a CLR List object that holds
a list of employees that you want to display in a ListBox. To create a
correspondence between these two objects, you would bind your employee
list to the ItemsSource property of the ListBox. However, suppose you
have a new employee joining your group. You might think that in order
to insert this new person into your bound ListBox values, you would
simply add this person to your employee list and expect this change to
be recognized by the data binding engine automatically.
That assumption would prove false; in actuality, the change will not
be reflected in the ListBox automatically. This is because the CLR
List object does not automatically raise a collection changed
event. In order to get the ListBox to pick up the changes, you would
have to recreate your list of employees and re-attach it to the
ItemsSource property of the ListBox. While this solution works, it
introduces a huge performance impact. Each time you reassign the
ItemsSource of ListBox to a new object, the ListBox first throws away
its previous items and regenerates its entire list. The performance
impact is magnified if your ListBox maps to a complex DataTemplate.
A very efficient solution to this problem is to make your employee
list an ObservableCollection. An ObservableCollection object
raises a change notification which the data binding engine can
receive. The event adds or removes an item from an ItemsControl
without the need to regenerate the entire list.
Update time for 1 item (ms)
To a CLR List object = 1656 ms
To an ObservableCollection = 20 ms
WPF never binds directly to a collection. If you specify a collection as a binding source, WPF actually binds to the collection's default view.
A collection view is a layer on top of a binding source collection
that allows you to navigate and display the source collection based on
sort, filter, and group queries, without having to change the
underlying source collection itself. A collection view also maintains
a pointer to the current item in the collection. If the source
collection implements the INotifyCollectionChanged interface, the
changes raised by the CollectionChanged event are propagated to the
views.
The event will fire for every change.
The GUI does not have to react and refresh every time, it can postpone that.
I know WinForms will optimize this, I think WPF has a similar approach.
If you want to see how often the UI requests the fresh results expose it as a public property and put a debug line in the get (assessor) of the public property for myObservableCollection.