I have a view where I've got an object bound to a treeview. The object has a number of collections (of different types) so I'm using hiearchical templates with a CompositeCollection to display them in the treeview.
I've then got a textbox that is bound to the treeview's selectedItem. Here I'm serialising the selectedItem to XML and displaying it in the textbox for editing.
All good so far. However, the big problem I have is that I can't use 2-way databinding with the SelectedItem property of the treeview as it is read only.
How can I cleanly keep the textbox edits in sync with my object that is bound to the treeview?
I do not think you need to do two-way databinding on the SelectedItem itself, you should expose a property in the class of your bound object which returns the serialized string and upon set modifies the object appropriately. This should be easier than dealing with the object as a whole.
Your XML stream must be represented as a property on your SelectedItem node, and your TextBox must be bound to that, somehow. The SelectedItem is read-only, but the object it refers to is not. If you two-way bind on that property, you should be able to affect your edits correctly. This would be done in the DataTemplates and HiearchicalDataTemplates you are using, since they are bound to the underlying data representation of the nodes you are representing with the TreeView.
Related
Well..its working BUT only when user creates a property that is of type List.
Here's the complete scenario.
I have a templated control (Multi Select ComboBox with Checkboxes)
User gives a List/ObservableCollection as its ItemsSource. The collection can be of any type (Employee, Chair, Person etc). The DependencyProperty for ItemsSource is of Type IList.
User can also give a List with two-way binding in a DependencyProperty called SelectedItems (so that he can show some items as checked and get back the items which gets checked)
Now the issue is with the SelectedItems dp. It is of type IList in the templated control.
The two-way binding does not work if user has bind it to, say, List<Person>.
But it works if List<Person> is changed to List<object>.
I cant figure out what is it that I am not doing right!
It doesn't make sense to place a TwoWay binding on the SelectedItems property. This would imply that the control should create and assign an instance of an object implementing IList to the property on the source object. However there is no way for control to know what actual type to create to assign to the property.
Instead you should be using a OneWay bind to a List that pre-exists in the source object albeit an empty one. The controls task then is to simply add or remove members in that list from the list supplied in the ItemsSource property.
So I have an ObservableCollection of items called "Class1" and
Class1 has a property named "ID".
I use a datagrid from the WPFToolkit and bind to this collection.
Within the datagrid is a combobox column and I bind it's ItemsSource to the ID property of the class.
At this point, all is good and everything populates as it should. What I want to do is modify the ObservableCollection to reflect the value selected in the ComboBox.
I have a ValueConverter bound to the SelectedItemBinding on the ComboBox as follows:
SelectedItemBinding="{Binding Path=ID, Converter={StaticResource IDConverter}}
What is the best (i.e: WPF approved method) of modifying the collection? When the IDConverter ConvertBack() method is called, I get the appropriate Class1 instance, but I can't access the Observable collection from within the ValueConverter and I also don't have access to the SelectedIndex value from the Datagrid.
I could create a class as a static resource with a pointer to my collection and pass that as a ConverterParameter, but that seems sort of hokey and I'm assuming there must be some slicker way of doing this with databinding.
For the record, a simple solution is to create a local resource with a reference to the collection you wish to modify as a dependency property. You can then pass this as a ConverterParameter and have access to it in the ConvertBack() interface method.
A caveat: You will most likely encounter a DeferRefresh exception when you make changes to the collection and then you lose focus.
An excellent fix is found here:
http://social.msdn.microsoft.com/Forums/en/wpf/thread/187b2b8f-d403-4bf3-97ad-7f93b4385cdf
Calling OnPropertyChanged for an ObservableCollection only works when there has been some change to the properties of the collection, not the objects it contains (add, remove, clear, etc).
Is there any way to notify the View that there has been a change to an item within the collection?
The objects it contains have to implement INotifyPropertyChanged as well. In your setter you trigger the event, and WPF will pick up on this and read in the new value as long as you are using two-way bindings or read-only bindings.
I'm having difficulty correctly Data Binding my models in the view. I have a MainWindowViewModel which contains a list of AlbumViewModels. Each AlbumViewModel holds an AlbumModel. So I have multiple albums and I need to display information in an ObservableCollection in the AlbumModel. I have two ListBoxes. ListBox1 holds the list of AlbumViewModels that are in my MainWindowViewModel. My second ListBox I want to display the ObservableCollection from the current selected item from the AlbumViewModel.AlbumModel. How can I do this? I've tried binding the DataContext of ListBox2 to the ListBox1 element, along with SelectedItem as the path but that returns 'AlbumViewModel'. Is there anyway to bind ItemsSource of a ListBox to the binding of the DataContext, but in this case binding it to [DataContext].AlbumModel.ObservableCollection or something?
I apologise if it sounds rather complicated!
You can use the fact, that when you bind to a collection, WPF wraps collection to CollectionView. And this guy has CurrentItem.. Bea had good article: How can I sync selection of two data bound ListBoxes? and Dr.WPF is amazing (as usual): ItemsControl: 'C' is for Collection.
I have a silverlight ListBox that has it's ItemsSource set. From the C# code behind I want to loop through each ListBox item and change the value of the text and access controls that are in the ListBox ItemTemplate. How would I do that?
ListBox controls in silverlight are bound to an ienumerable type, so that if any value in the ListBox changes, the underlying data is changed and vice versa depending on what type of binding you require. To effectively iterate the items you'll want to iterate through the enumerable object you've bound to.
You can get to the collection by accessing the ListBox.ItemsSource property and change the text of appropriate items, perform LINQqueries etc. If you have bound the controls correctly, saving the collection should update the list.
Hope this helps!