Skip to main content
Home Forums Silverlight Programming Silverlight Controls and Silverlight Toolkit ComboBox with SelectedValuePath
11 replies. Latest Post by Insumo on August 20, 2009.
(1)
ZeekJones
Member
4 points
5 Posts
11-28-2008 12:09 PM |
Unless I missed a property somewhere, a SelectedValue property is needed for combo boxes and list boxes. I extended a combo box to do this.
If you have business objects that store data in a database via databinding, you've probably already found it a pain not to be able to associate a value with an item in a dropdown when selected. Currently you have to do it manually. I was adding bussiness objects to the list and having to determine the value based on the selection. The DisplayMemberPath and SelectedItem works great but with the SelectedValuePath its complete. Check out the code:
http://www.engineserver.com/silverlightcombobox/
Jonathan...
All-Star
24979 points
2,434 Posts
12-03-2008 9:55 PM |
Hi ZeekJones,
Yes. I agree with you on the ComboBox's SelectedValue issue. Thanks for sharing your brilliant work here. Currently, SelectedValue is not supported on Silverlight ComboBox. We need to create a Custom control just like you did. As an alternative, we found another way. Please see my reply on this thread. Thanks. With all the community members contribution, our forum become more and more valuable.
Best regards,
Jonathan
Andrejt
Participant
756 points
113 Posts
01-15-2009 3:32 PM |
Hi, ZeekJones,
may I suggest a minor improvement to your great extension? Your current implementation doesn't handle things properly when ComboBox and its properties are set through the Xaml. In this case, SelectedValue never gets called.
The solution to this would be to register the SelectedValuePropertyDP with the overload that specifies the PropertyChangedCallback delegate and move the setter logic into that handler:
public static readonly DependencyProperty SelectedValueProperty = DependencyProperty.Register("SelectedValue", typeof(object), typeof(BindingComboBox), new PropertyMetadata((object)null, new PropertyChangedCallback(OnSelectedValueChanged)));
private static void OnSelectedValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { // Set selected item here }
This would alow something like:
<controls:FixedComboBox DisplayMemberPath="Value" SelectedValuePath="Key" ItemsSource="{Binding MyDictionary, Source={StaticResource dictionaries}}" SelectedValue="{Binding MyValue, Mode=TwoWay}" />
Thanks,Andrej
01-15-2009 9:26 PM |
That makes sense. Thanks for the improvement.
hehrsson
26 points
71 Posts
01-16-2009 5:59 AM |
Hmm, can't get it to work.
I get an error on Items on the Linq query.
And could you please update your code example with the improvement that Andrej posted?
Thanks,Håkan
01-16-2009 6:08 AM |
Håkan,
have you included the "using System.Linq" directive in your derived control?
Andrej
jwilcox
1082 points
187 Posts
01-16-2009 6:16 AM |
Any chance you could share the actual exception message with us?Thanks,
01-16-2009 7:40 AM |
Aaah, it was the using System.Linq; that was missing, thanks!
- Håkan
Cyse
3 Posts
02-21-2009 11:09 AM |
Hello,
I can't get it working!
I have in my xaml:
... <StackPanel x:Name="spClient" DataContext="{Binding}" Orientation="Vertical"> <TextBox Width="150" Text="{Binding nom, Mode=TwoWay}" /> <custom:ComboBoxClassic x:Name="cbLangue" DisplayMemberPath="langue" SelectedValuePath="langueId" ItemsSource="{Binding}" SelectedValue="{Binding langueId, Mode=TwoWay}" /> ...
The ItemsSource of Combo is IEnumerable<Langue>:
public class Langue { public int langueId { get; set; } public String langue { get; set; } }
The DataContext of StackPanel is an object of type Client:
public class Client : INotifyPropertyChanged { public int clientId { get; set; } public String nom { get; set; } public int langueId { get; set; } public event PropertyChangedEventHandler PropertyChanged; }
If I edit the textbox then the client object have it's "nom" property changed automatically.
If I select a value in the comboBox client.langueId is not changed...
What am I doing wrong?
Thanks.
02-23-2009 2:52 PM |
Hi again,
It works now: I was populating the DataContext of the comboBox instead of its ItemsSource in the code behind.
But I made a little change also to be able to set the SelectedValue BEFORE the comboBox is filled of items. The DropDownList in ASP.NET has this behaviour too and I think it's important because of the asynchronous environment of SilverLight. I also filled the SelectedValuePropertyChanged to have the good value on first binding.
using System;using System.Linq;using System.Windows;using System.Windows.Controls;/// <summary>/// Extended ComboBox that provide SelectedValueProperty and SelectedValue for asp:DropDownList-like capabilities./// Original version by ZeekJones: http://www.engineserver.com/silverlightcombobox//// Improved by andrejt: http://silverlight.net/forums/p/53720/139118.aspx#139118 : DependencyProperty./// Improved by cyse: http://silverlight.net/forums/p/53720/139118.aspx#178204: SelectedValue cache./// </summary>public class ComboBoxClassic : ComboBox{ private Object _selectedValue; public static readonly DependencyProperty SelectedValuePathProperty = DependencyProperty.Register("SelectedValuePath", typeof(String), typeof(ComboBoxClassic), new PropertyMetadata(new PropertyChangedCallback(SelectedValuePathPropertyChanged))); public static readonly DependencyProperty SelectedValueProperty = DependencyProperty.Register("SelectedValue", typeof(Object), typeof(ComboBoxClassic), new PropertyMetadata(new PropertyChangedCallback(SelectedValuePropertyChanged))); public ComboBoxClassic() : base() { base.SelectionChanged += new SelectionChangedEventHandler(ComboBoxClassic_SelectionChanged); } private void ComboBoxClassic_SelectionChanged(Object sender, SelectionChangedEventArgs e) { if (SelectedItem != null && !string.IsNullOrEmpty(SelectedValuePath)) { SetValue(ComboBoxClassic.SelectedValueProperty, SelectedItem.GetType().GetProperty(SelectedValuePath).GetValue(SelectedItem, null)); } } protected override void OnItemsChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { base.OnItemsChanged(e); if (_selectedValue != null) { SelectedValue = _selectedValue; } } private static void SelectedValuePathPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ComboBoxClassic cb = d as ComboBoxClassic; cb.SelectedValuePath = e.NewValue.ToString(); cb.SelectedValue = cb.SelectedValue; } private static void SelectedValuePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ComboBoxClassic cb = d as ComboBoxClassic; cb.SelectedValue = e.NewValue; } /// <summary> /// The name of the property in the ItemsSource objects that "SelectedValue" will return. /// </summary> public string SelectedValuePath { get { return (string)GetValue(ComboBoxClassic.SelectedValuePathProperty); } set { SetValue(ComboBoxClassic.SelectedValuePathProperty, value); } } /// <summary> /// The value of the property specified by SelectedValuePath in the selected item. /// </summary> public object SelectedValue { get { return GetValue(SelectedValueProperty); } set { _selectedValue = value; var q = (from item in Items where item.GetType().GetProperty(SelectedValuePath).GetValue(item, null).Equals(value) select item).FirstOrDefault(); if ( q!= null) { SelectedItem = q; } } }}
AlphaLima
9 points
13 Posts
03-27-2009 12:51 PM |
I get the following error when attempting to bind to the itemsource :
Items collection must be empty before using ItemsSource.
So I cleared the items before binding to itemsource and got this error "Object reference not set to an instance of an object." on second line below (from your code)
Just to clarify, if I leave those three lines in, I get the error: Items collection must be empty before using ItemsSource.
And if I clear the items, then I get an Object reference not set to an instance of an object stemming from those three lines.
Insumo
2 points
1 Posts
08-20-2009 4:55 PM |
Thanks, creating a custom ComboBox worked great!