Skip to main content
Microsoft Silverlight
Home Forums Silverlight Programming WCF RIA Services Set ComboBox SelectedItem from DomainService
7 replies. Latest Post by Brujeador on November 18, 2009.
(0)
Brujeador
Member
1 points
8 Posts
11-17-2009 2:58 PM |
As many people, for what I’ve read, I’m having an issue with the combobox. I am able to populate the combobox through code behind and xaml but I can not set the SelectedItem to a default value from the list. I have tried a number of different approaches but none work so far.
My specific scenario is that I have a languages table with three colums(languageId/languageName/languageSelected). I am successfully populating a combobox at the top of the MainPage with the languages list through a domain service. When the page is loaded I want the combobox to be set to the language which is marked as the selected language(“language.languageSelected =true”) in the database. How can I accomplish this specific requirement?
bryant
Star
10089 points
1,655 Posts
11-17-2009 3:07 PM |
You should be able to set this using a Binding and a ValueConverter. Point the Binding to the same list of languages as the combobox ItemsSource is pointing to. In the ValueConverter return the item that has languageSelected = true.
11-17-2009 5:40 PM |
Thanks for your reply. I've read a little bit about using converters but I still don't get the concept of how they work and why they are needed to accomplish this. I've found some examples that I'm trying to follow and here's my first shot at it:
The converter as a resource in the xaml:
</UserControl.Resources>
<ComboBox x:Name="cbLanguage" ItemsSource="{Binding Data, ElementName=ddsLanguages}" SelectedItem="{Binding Language, Mode=TwoWay, Converter={StaticResource LanguageConverter}, ConverterParameter={Binding Data, ElementName=ddsLanguages}}" DisplayMemberPath="languageName" />
<ComboBox x:Name="cbLanguage" ItemsSource="{Binding Data, ElementName=ddsLanguages}"
SelectedItem="{Binding Language, Mode=TwoWay,
Converter={StaticResource LanguageConverter},
ConverterParameter={Binding Data, ElementName=ddsLanguages}}"
DisplayMemberPath="languageName" />
public class LanguageConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { var languages = (IEnumerable)parameter; foreach (Language lang in languages) { if ((bool)lang.languageSelected) { return lang; } } return null; } }
When I run this I get an error:
"Invalid attribute value {Binding Language, Mode=TwoWay,
Converter={StaticResource LanguageConverter}, ConverterParameter={Binding Data,
ElementName=ddsLanguages}} for property SelectedItem."
By the description I'm thinking it has to do with the converter parameter. Can someone look at my code above and give me guidance as to what I may need to change/add. Thank you.
11-17-2009 7:40 PM |
Part of the issue is that typically you would be binding this to just a property on your ViewModel (like SelectedLanguage). In your case you want to bind it to the list item that has a certain property, so you need to use a converter to go from a list to a single item.
I'll take a look at your code to see what I can find.
11-17-2009 7:41 PM |
ConverterParameter is only a string value (and is passed in as parameter).
11-17-2009 7:47 PM |
Here is how you could implement this:
public class LanguageConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { var languages = (IEnumerable)parameter; return languages.Where(l => l.languageSelected == true).SingleOrDefault(); } }
<ComboBox x:Name="cbLanguage" ItemsSource="{Binding Data, ElementName=ddsLanguages}" SelectedItem="{Binding Data, ElementName=ddsLanguages, Converter={StaticResource LanguageConverter}}" DisplayMemberPath="Name" />
This only gets you to the first step. If you now want to have the selected language change then you'd have to implement a convert back method.
Really you'd be a lot better off having a SelectedLanguage property somewhere and binding directly to that instead of this.
pthomasius
18 points
4 Posts
11-18-2009 3:45 AM |
You could always do it the classic way in code behind. You'll need a OnLoaded method for your data call and then you can do something like: ListBox.SelectedItem = (ListBox.ItemsSource as EntityList<YourType>).Where(x=> x.SelectedLaguage == true).FirstOrDefault();You might have to cast the ItemSource to something else then EntityList depending on what your query returns.
11-18-2009 6:43 PM |
Thanks Bryant and Pthomasius for your help. I've managed to accomplish what I was trying to do. Here's how.
public MainPage() { InitializeComponent(); this.Loaded += new RoutedEventHandler(Page_Loaded); } void Page_Loaded(object sender, RoutedEventArgs e) { context.Load(context.GetLanguagesQuery(), MergeOption.KeepCurrentValues, OnLanguagesLoaded, null); } private void OnLanguagesLoaded(LoadOperation lo) { cbLanguage.ItemsSource = lo.Entities; cbLanguage.DisplayMemberPath = "languageName"; cbLanguage.SelectedItem = cbLanguage.Items .OfType() .FirstOrDefault(lang => lang.languageSelected.Equals(true)); }
<ComboBox x:Name="cbLanguage" /> Before I was calling the Load method with the EntityQuery by itself and then trying to set the selectedItem as such: public MainPage() { InitializeComponent(); cbLanguage.ItemsSource = context.Languages; cbLanguage.DisplayMemberPath = "languageName"; context.Load(context.GetLanguagesQuery()); cbLanguage.SelectedItem = cbLanguage.Items .OfType() .FirstOrDefault(lang => lang.languageSelected.Equals(true)); } The combobox was being populated but the selectedItem wasn't being set. Thats when I started trying different approaches including what Bryant sugested. Reading some threads I found this approach. It has to do with the asynchronous nature of silverlight. If I'm not mistaken, please correct me if I am, with my first approach the call to the server was over by the time I was trying to set the selectedItem, which I'm still a bit confused about since the combobox was already populated. What is happening now is that I'm doing what I need to do during the call at which point all the data is available to work with.
<ComboBox x:Name="cbLanguage" />
Before I was calling the Load method with the EntityQuery by itself and then trying to set the selectedItem as such:
public MainPage() { InitializeComponent(); cbLanguage.ItemsSource = context.Languages; cbLanguage.DisplayMemberPath = "languageName"; context.Load(context.GetLanguagesQuery()); cbLanguage.SelectedItem = cbLanguage.Items .OfType() .FirstOrDefault(lang => lang.languageSelected.Equals(true)); }
The combobox was being populated but the selectedItem wasn't being set. Thats when I started trying different approaches including what Bryant sugested. Reading some threads I found this approach. It has to do with the asynchronous nature of silverlight. If I'm not mistaken, please correct me if I am, with my first approach the call to the server was over by the time I was trying to set the selectedItem, which I'm still a bit confused about since the combobox was already populated. What is happening now is that I'm doing what I need to do during the call at which point all the data is available to work with.