Skip to main content

Microsoft Silverlight

Answered Question ComboBox with SelectedValuePathRSS Feed

(1)

ZeekJones
ZeekJones

Member

Member

4 points

5 Posts

ComboBox with SelectedValuePath

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 Shen – MSFT
Jonathan...

All-Star

All-Star

24979 points

2,434 Posts

Microsoft
Answered Question

Re: ComboBox with SelectedValuePath

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

 

 

Jonathan Shen
Microsoft Online Community Support
Please remember to mark the replies as answers if they help and unmark them if they provide no help.

Andrejt
Andrejt

Participant

Participant

756 points

113 Posts

Silverlight MVP
Answered Question

Re: ComboBox with SelectedValuePath

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 

Andrej Tozon
MVP - Client Application Development | Blog | Twitter

ZeekJones
ZeekJones

Member

Member

4 points

5 Posts

Re: ComboBox with SelectedValuePath

That makes sense.  Thanks for the improvement.

hehrsson
hehrsson

Member

Member

26 points

71 Posts

Re: ComboBox with SelectedValuePath

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

Andrejt
Andrejt

Participant

Participant

756 points

113 Posts

Silverlight MVP

Re: ComboBox with SelectedValuePath

Håkan,

have you included the "using System.Linq" directive in your derived control?

Andrej

Andrej Tozon
MVP - Client Application Development | Blog | Twitter

jwilcox
jwilcox

Participant

Participant

1082 points

187 Posts

Microsoft

Re: ComboBox with SelectedValuePath

Any chance you could share the actual exception message with us?
Thanks,

Jeff Wilcox [MSFT]
Silverlight
http://www.jeff.wilcox.name/blog/

This posting is provided "AS IS" with no warranties, and confers no rights.

hehrsson
hehrsson

Member

Member

26 points

71 Posts

Re: ComboBox with SelectedValuePath

Aaah, it was the using System.Linq; that was missing, thanks!

- Håkan

Cyse
Cyse

Member

Member

4 points

3 Posts

Re: ComboBox with SelectedValuePath

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.

Cyse
Cyse

Member

Member

4 points

3 Posts

Re: ComboBox with SelectedValuePath

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
AlphaLima

Member

Member

9 points

13 Posts

Re: Re: ComboBox with SelectedValuePath

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) 

ComboBoxClassic cb = d as ComboBoxClassic;
 cb.SelectedValuePath = e.NewValue.ToString();
cb.SelectedValue = cb.SelectedValue;

 So I commented those three lines and it is working..

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
Insumo

Member

Member

2 points

1 Posts

Re: ComboBox with SelectedValuePath

Thanks, creating a custom ComboBox worked great!

  • Unanswered Question
  • Answered Question
  • Announcement
Microsoft Communities