Silverlight ComboBox Sample for RIA Services


I’ve been intending to write a sample using the ComboBox for a while. The more familiar you get with Silverlight, the more you realize the ComboBox causes all sorts of problems. I have mixed feelings about the proliferation of posts I’ve seen on this topic; on one hand, it’s great to see everyone getting involved; on the other, it points to serious problems with basic scenarios.

The Challenges

I’ve seen a few good posts out there using the DomainDataSource with a ComboBox that make things look easy. Since those were already well trodden paths I thought it would be important to identify some of the harder scenarios. After a bit of investigation, three things came forward as being particularly difficult.

  • Loading ComboBox contents asynchronously
  • Implementing cascading ComboBoxes
  • Using ComboBoxes for Entity associations

 

The Sample

I’ve included a sample along with the post to get you started. It includes a small library of extensions for you to reuse and shows how you can use them. This extension namespace will pop up throughout the rest of the post.

  xmlns:ex="clr-namespace:ComboBoxExtensions;assembly=ComboBoxExtensions"

I wanted to put together a simple declarative syntax for using ComboBoxes. I figured the task wasn’t that complex so the code shouldn’t be either. It seemed like most tasks should be doable with a data source, a ComboBox, and a few simple bindings.

  <ex:ComboBoxDataSource Name="ASource"

                         DomainContext="{StaticResource SampleDomainContext
}"

                         OperationName="GetAValues" />

  .
..

  <ComboBox Name="AComboBox"

           
ItemsSource="{Binding Data, ElementName=ASource}"

           
SelectedItem="{Binding A, Mode=TwoWay}"

           
ex:ComboBox.Mode="Async" />

Here are a few things to notice when you crack open the sample.

  • AComboBox uses a simple binding to a static list
  • BComboBox binds to a list that is dynamically changing based on what is selected in A
  • CComboBox is bound to a dynamic list of Entities that changes based what is selected in B and is used to modify associations
  • I use a partial class and shared validation to fully enforce the relationships defined in the ComboBoxes

As I wrote this sample I experienced plenty of missteps and restarts. Along the way, I came to a few conclusions.

1) Do not use the DomainDataSource to populate ComboBoxes

You might think this is drastic or an over reaction, but I stick by the recommendation. Despite the simple samples you’ll see in other places, I think you’re better off avoiding the DDS when working with ComboBoxes. The DDS does not scale for more complex ComboBox scenarios. You’re better off having your own data source that you can use throughout your application. If you don’t want to write one yourself, I’ve included a simple data source in the sample.

  <ex:ComboBoxDataSource Name="ASource"
DomainContext="{StaticResource SampleDomainContext}"
OperationName="GetAValues" />

[In the spirit of full disclosure, I’m the primary developer for the DomainDataSource control going forward. Integration with ComboBoxes is one of the features I’m investigating.]

2) Share the DomainContext

If you want to associate Entities, they need to be in the same DomainContext. To accomplish this, the data source that loads entities for associations must not have its own instance of a DomainContext. Instead, it should be using the same DomainContext used to load the primary entities. I found it useful to create the DomainContext as a StaticResource in xaml and use it throughout.

  <UserControl.Resources>
    <web:SampleDomainContext x:Key="SampleDomainContext" />
  </UserControl.Resources>
...
<ex:ComboBoxDataSource Name="ASource"
DomainContext="{StaticResource SampleDomainContext}"
OperationName="GetAValues" />

3) Using the ComboBox asynchronously is hard

The ComboBox did not help me at all as I tried to asynchronously load data and constantly behaved in ways I did not anticipate. To address these limitations and quirks the extension library adds two modes to make asynchronous data loading a breeze whether you’re declaring the source or using a view model.

  • Async – The SelectedItem and ItemsSource can be updated in any order. If the SelectedItem is set first, the ComboBox may appear blank until the items are loaded.
  • AsyncEager – Just like the Async mode, the SelectedItem and ItemsSource can be updated in any order. Unlike the first mode, this one eagerly selects anything you tell it to. The next time the list is loaded it confirms the selection is valid.

  <ComboBox Name="AComboBox"

           
ItemsSource="{Binding Data, ElementName=ASource}"

           
SelectedItem="{Binding A, Mode=TwoWay}"

           
ex:ComboBox.Mode="AsyncEager" />

I found the user experience with AsyncEager to be nicer. However, there are some edge cases with SelectedValue where the behavior of Async seemed to be a better choice.

In Conclusion

I hope the next version of Silverlight (v5) addresses some of these concerns. It’d be great if the control were designed for asynchronous scenarios. Also, I’d love to hear what you think about data sources for the ComboBox. Would the ComboBoxDataSource included in the sample be sufficient if we shipped it in the toolkit? Are there DomainDataSource features you think are critical for this scenario that are not included in the ComboBoxDataSource? Would you prefer if we supported all ComboBox scenarios with just the DomainDataSource?

Hope the sample helps and thanks in advance for the feedback.

Frequently Asked Questions

There have been a number of questions asked throughout the comments on this post. To make things easy for you, I’ve aggregated the questions and provided a little more detail in my answers in this new post.

Silverlight ComboBox Frequently Asked Questions

Now on NuGet

Colin did me the favor of putting the Extension library up on NuGet (as part of RiaServiceContrib). You can find it under RiaServicesContrib.ComboBoxExtensions.

Comments (94)

  1. Colin Blair says:

    This is really nice work Kyle, and it works nicely with my recent series on exposing collections of entities from a ViewModel. This is the similar problem of how to do it without a ViewModel.

  2. sladapter says:

    Kyle,

    I haven't tried your sample yet.  But I just want to add a quick note to thank you for writing up this blog. Finally we have someone from MS to confirm the current ComboBox has problems with it's basic design to work with DomainDataSource.

    The ComboBox has given us all kinds of headaches. All business applications depend on this control.  Hope your team and Control team will address this problem quickly.

    Will report back after I try this ComboBoxDataSource.

  3. Windiestpeak says:

    I say don't knock it if you haven't tried it' so I shall

  4. Alexander G. Bykin says:

    Hi Kyle

    Thank you very much for working with community, your solution is really helpful and fixing the problem.

    But i have troubles with ComboBox modes, when i try set is to:

    – Default – can't see records when dropping down;

    – Async – can't see records when dropping down;

    – AsyncEager – data coming, but when droping down ComboBox i see only one record, but must be some;

    Fix it please and give us solution.

    Thanks.

  5. Alexander G. Bykin says:

    ok, i found problem, fact is that we need to mark our methods of the DomainDataService (on server side) as [Invoke], but if we do that, we must return IEnumerable or duplicate methods for returning IEnumerable and its sounds like bad news, because i do not need to dublicate methods.

    so, why ComboBoxDataSource is not working with IQueryable<ENTITY_TYPE> ?

  6. kylemc says:

    The ComboBoxDataSource requires the operation name generated on the client. For Invoke methods, this will be identical to what you wrote on the server, but Query methods will need "Query" appended to the end.

  7. Alexander G. Bykin says:

    Hi Kyle,

    thanks for feedback, i follow your recommendation but when i mark my method as [Invoke], i have error message after compilation:

    Error 1 Operation named 'GetAgreementType' does not conform to the required signature. Return types must be an entity, collection of entities, or one of the predefined serializable types. ExpressCreditService

    method looks like:

    [Invoke]

    public IQueryable<AgreementType> GetAgreementType()

           {

               return this.ObjectContext.AgreementType;

           }

    it about dublication of existing methods, i do not need to dublicate existing methods and replacing return types, because i have so many tables like this, than i need to connect with ComboBox

  8. Alexander G. Bykin says:

    Kyle, I do not understand you correctly when you wrote about the attributes for the methods, excuse me, I think about it you definitely need to write in a blog post.

    I again read your email-messages and use the attribute [Query] with my method:

    [Query]

    public IQueryable <AgreementType> GetAgreementType ()

    (

       return this.ObjectContext.AgreementType;

    )

    and used it on the client OperationName = "GetAgreementTypeQuery"

    and launched with debugger, the data come into ComboBoxDataSource, but the ComboBox-extension does not display the data obtained, only one entry which comes from the parent record.

  9. kylemc says:

    @Alexander

    Thanks for sending me your repro. The point I want to reiterate here is the DataGrid and DataForm do not support the same kind of ElementName binding that everything else does. There is a boundary between the full UI tree and the DataTemplate and ElementName binding cannot cross that boundary. In the sample, I moved the data sources inside the DataForm DataTemplate so I could use ElementName binding. Alternately, I could have made the data sources Resources and bound to them directly as StaticResources.

  10. Matt Houser says:

    http://www.houser.ca/…/ComboTest1-2.zip

    The ComboBox on the ChildWindow in this sample does not select the correct entry when using the DDS or the CBDS.

    …Matt

  11. Alexander G. Bykin says:

    Matt Houser

    read carefully what wrote Kyle at 06-22-2010 7:11 PM

    look at this sample, all working fine:

    cid-a47796b098a35137.office.live.com/…/SlApp.zip

  12. kylemc says:

    @Matt

    Thanks. Another little nit I left out of the post. The 'ex:ComboBox.Mode' property needs to be set at the very end. Everything must already be specified for it to work its magic. Frustrating at first, but hopefully you won't run into again.

  13. Les Prigmore says:

    Hi Kyle, Thanks for the great explanation. How could we make this work in a DatatGrid? I've been trying to make that work for days now and it is driving me nuts. Could you update your example with it working in the DataGrid?

    I much appreciate your help………….Thanks & Have a great day……….Les

  14. kylemc says:

    @Les

    The problem with DataGrid is that it's less clear what you should do. I'd argue you really don't want cascading ComboBoxes (like I show in the sample) in a DataGrid. Keeping that in mind, you can do it if you have to. Here are the templates for Columns A and B.

                           <dg:DataGridTemplateColumn Header="A_CB" >

                               <dg:DataGridTemplateColumn.CellTemplate>

                                   <DataTemplate>

                                       <Grid Margin="4">

                                           <TextBlock Text="{Binding A}" VerticalAlignment="Center"/>

                                       </Grid>

                                   </DataTemplate>

                               </dg:DataGridTemplateColumn.CellTemplate>

                               <dg:DataGridTemplateColumn.CellEditingTemplate>

                                   <DataTemplate>

                                       <Grid>

                                           <ex:ComboBoxDataSource Name="DG_ASource" DomainContext="{StaticResource SampleDomainContext}" OperationName="GetAValues" />

                                           <ComboBox Name="DF_AComboBox"

                                                     ItemsSource="{Binding Data, ElementName=DG_ASource}"

                                                     SelectedItem="{Binding A, Mode=TwoWay}"

                                                     ex:ComboBox.Mode="AsyncEager" />

                                       </Grid>

                                   </DataTemplate>

                               </dg:DataGridTemplateColumn.CellEditingTemplate>

                           </dg:DataGridTemplateColumn>

                           <dg:DataGridTemplateColumn Header="B_CB" >

                               <dg:DataGridTemplateColumn.CellTemplate>

                                   <DataTemplate>

                                       <Grid Margin="4">

                                           <TextBlock Text="{Binding B}" VerticalAlignment="Center"/>

                                       </Grid>

                                   </DataTemplate>

                               </dg:DataGridTemplateColumn.CellTemplate>

                               <dg:DataGridTemplateColumn.CellEditingTemplate>

                                   <DataTemplate>

                                       <Grid>

                                           <ex:ComboBoxDataSource Name="DG_BSource" DomainContext="{StaticResource SampleDomainContext}" OperationName="GetBValues">

                                               <ex:ComboBoxDataSource.Parameters>

                                                   <ex:Parameter ParameterName="a" Value="{Binding A}" />

                                               </ex:ComboBoxDataSource.Parameters>

                                           </ex:ComboBoxDataSource>

                                           <ComboBox Name="DF_BComboBox"

                                                     ItemsSource="{Binding Data, ElementName=DG_BSource}"

                                                     SelectedItem="{Binding B, Mode=TwoWay}"

                                                     ex:ComboBox.Mode="AsyncEager" />

                                       </Grid>

                                   </DataTemplate>

                               </dg:DataGridTemplateColumn.CellEditingTemplate>

                           </dg:DataGridTemplateColumn>

    Since 'A' is a query returning static results, you could remove the CBDS from the template, move it into the page resources, and then bind to it using a {StaticReference}. Also, I found DataGrid required me to implement more explicit validation and return the member name with every ValidationResult. Here's what I changed ValidateAssociation to.

           public static ValidationResult ValidateAssociation(EntityC entity, ValidationContext context)

           {

               if (entity == null)

               {

                   return new ValidationResult("Value is not set", new[] { context.MemberName });

               }

               return ValidationResult.Success;

           }

    Hope that helps.

  15. Chui Tey says:

    Thanks Kyle. Any reason why you used OperationName instead of QueryName on ComboBoxDataSource so that we can use it as a drop-in replacement for DomainDataSource?

  16. kylemc says:

    It doesn't behave exactly the same. QueryName only worked with Query operations and would infer the 'Query' part of the name. OperationName can be used with Query and Invoke operations and requires the name to be fully specified. Feel free to link the source into your project and make the updates yourself to enable drop-in replacement if that would save you some time.

  17. Chui Tey says:

    Thanks Kyle for working so late at night!

    The semantics are different, you made the right call.

    By the way, I'm having problems with SelectedValueMode in your demo.

    In MainPage.xaml, I tried

                               <ComboBox Name="DF_CComboBox2"

                                         ItemsSource="{Binding Data,ElementName=DF_CSource}"

                                         SelectedValuePath="Id"

                                         SelectedValue="{Binding CId, Mode=TwoWay}"                                      

                                         ex:ComboBox.Mode="Async"/>

    But it resulted in the comboboxes appearing as blank. I'm still stepping through code, but would appreciate any help you can offer.

  18. Chui Tey says:

    Resolved it.

    The ComboDataSource has to be *inside* the DataForm.

  19. CybexMInd says:

    Hi, why not create a final version of the control to be included in RIA Toolkit or Silverlight Toolkit?

  20. kylemc says:

    @CybexMind

    Thanks. I've considered putting the data source in the RIA Toolkit. It'd require a little more polish, but I think it could be worth it.

  21. Peter Wone says:

    > The point I want to reiterate here is the DataGrid and DataForm do not support

    > the same kind of ElementName binding that everything else does. There is a

    > boundary between the full UI tree and the DataTemplate and ElementName binding

    > cannot cross that boundary. In the sample, I moved the data sources inside the DataForm

    > DataTemplate so I could use ElementName binding.

    That was what I needed. I've moved the declaration of my DDS inside the template.

    I have a horrible feeling that this means I'm going to get a fresh instance for every row in the DataGrid – would this be correct?

    This innocuous little paragraph of yours nicely encapsulates an issue that is the fount of many woes. In my not terribly humble opinion, something must be done about this. Frankly I think they both need a rethink and a rewrite. Yes, I do know the enormity of what I've just suggested. I have a very good idea of how hard it is to produce a good quality grid, and an appreciation of how much might be entailed.

    But it's IMPORTANT. The DataGrid is a mainstay of LOB development, and use of ComboBoxes to express FK lookups is a core scenario.

    Seriously, if you guys have too much on, and I can well believe you do, it would do Microsoft much credit  to reach out to the dev community for help by open sourcing the DataGrid.

    And the ComboBox, for that matter.

  22. kylemc says:

    @Peter

    Not necessarily correct. If you put the data source inside the edit template, you'll get one instance for that column that will re-databind every time you try to edit. If you put it inside the cell template, then you'll get one instance per visible row.

    Also keep in mind that I would only endorse putting a data source in the template if you must have dynamic content (cascading lookups, etc). If you content is static (may or may not be asynchronously loaded), then I'd recommend making your data source a control Resource and using StaticReference binding. Even in the small set of scenarios where it's required, it might be better to consider a different UI design.

    Thanks for the feedback. I'll make sure it gets to the right people.

  23. David Zuber says:

    Thanks a lot for this add, it has fixed me a lot of problems,

    I have now another problem, if I use your solution my combobox lost all the defined tag that I have defined in my service metadata file :

    <Include()> _

           <Display(Name:="Expense Type", ShortName:="Ex. Type", Description:="Please defined the expense type")> _

           Public Property ExpenseType As ExpenseType

    XAML code of my view page for the dataform :

                          <toolkit:DataField>

                               <ComboBox ItemsSource="{Binding Source={StaticResource ExpensesPayments}, Path=Data}"

                                         DisplayMemberPath="ExPaName"

                                         SelectedItem="{Binding Path=ExpensePayment, Mode=TwoWay}"                              

                                         Name="ComboBox1"  

                                         ex:ComboBox.Mode="Async"  >

                               </ComboBox>

                           </toolkit:DataField>

    Is that a known problem or I do something wrong …

    Many thanks for your help

  24. kylemc says:

    @David

    I'm not sure exactly what you're asking. I assume you're saying "I used to use DataForm field auto-generation and would see my DisplayAttribute values for each field. Now that I explicitly define my template I do not see those values." I think it's a limitation of the DataForm.

    In this post, Jeff describes how to hook into auto-generation (jeffhandley.com/…/lookupdata.aspx). In your case, you'll want to do something like this.

    if (e.PropertyName == "ExpensePayment")

    {

     ComboBox comboBox = new ComboBox();

     // … set all the properties except SelectedItem and Mode

     // This next call is an extension method defined in the business application template

     e.Field.ReplaceTextBox(comboBox, ComboBox.SelectedItemProperty); // Sets SelectedItem Binding

     ComboBoxExtensions.ComboBox.SetMode(comboBox, ComboBoxMode.Async); // Sets Mode

    }

    Feel free to contact me if you need this example fully written out.

  25. Andrew Lindzon says:

    My first use for a combobox is from a table but static.  I would like to use it for both datagrid's and forms.  Simply I have created a table with all the states/provinces from north america.  Rather than trust the users to enter one, and to know the 2 character codes, I would like a drop down list to appear that they can use to select the correct code.  The list should show both the StateID (2 character code), and the Name.  I am not sure which way it should be sorted, opinions are appreciated.

    But that aside, I would appreciate an example of how you would use this with a datagrid.  I noticed your comments above that if the resource is statis you would take a slightly different approach.

    The list of states is in a table States.  Customers has a 0,1 relationship to states, i.e. the field can be null.

    I have copied the ComboBox.Extensions project, so I am ready to use them.

    My next use is not static, since I will want to want to relate a salesrep to the customer.

    Thank you.

  26. Bavo Ketels says:

    Amazing stuff.

    It works great. Thanks a lot.

  27. kylemc says:

    @Andrew

    If you have a static list, I would recommend creating a single instance of the data source. For example, I might choose to put it in the App or MainPage resources. Then I would just link it anywhere I needed using {StaticResource} binding. The benefit of resource binding is that it's available everywhere including DataGrid and DataForm templates (while ElementName binding is not). I think I'd still recommend using an async mode in your combo boxes so you don't have to worry about how long it takes the data source to load (the alternative is waiting for the load to complete before creating UI that references it). Hopefully that explanation makes enough sense to get you started.

  28. What if there is a list of 400 items and I want to select one with the "combo"box?

    I wrote "combo" because where is the combination? it's more like a drop down list.

    I can't type anywhere, showing me only the items starting with the typed letters!

    Can the SlApp (mentioned before in the comments) be rewritten, showing the combobox in the datagrid, only showing when the datagrid is entering editing mode? with a datapage control. And… still being showed after going to the next page.

    And when it is possible to add a new item at the bottom of the datagrid (although this topic is about comboboxes) I would be very very happy.

    …..Just another struggler trying to get those comboboxes to work…..

  29. kylemc says:

    @Marcel

    You're right, it is more of a drop-down list. If you want auto-complete, take a look at the AutoCompleteBox shipped in the Silverlight Toolkit.

    Did you see the big block of xaml I put on the first page of the comments? It shows how to put a TextBlock in the CellTemplate and a ComboBox in the EditTemplate. That should be what you're looking for.

    I hear a number of people have asked for the ability to add new items. Hopefully they'll be able to add it to the DataGrid in SL5.

  30. Marcel Marnix says:

    Thanks Kyle,

    After 8 weeks of trying, I've got everything to work…

    Multiple comboboxes in a datagrid, displaying data from a relational database, only showing a combobox when the datagrid is in editing mode. With Datapager, Filter Queries… etc.

    I am going to try the AutoCompleteBox now!

    I have seen a sample of adding Items to the end of the row… Somewhere… The Problem is I have so many Favorites, I can't find them anymore 😉

    🙂 🙂 🙂 One Happy Programmer

  31. Bruno Lopes says:

    Can please someone tell me how can I use or to combine comboboxes to choose Country, State, City… etc…. All my combobox are feeded by RIA services and I want to do something like your sample Kyle, passing parameters between them. I think I'm able to do so but I still couldn't find a way to cast the selected item to Entity. Can you please help me with that?

    Thank you.

  32. kylemc says:

    @Bruno

    Take a close look at ComboBox "C" in my sample. It works with a list of entities and associates the selected one with the SampleEntity instance (just like a City would do with a State). If you have a sample that isn't quite working, feel free to contact me via the blog, and I'll help you take a look at it.

  33. Bruno says:

    Finaly I have my comboboxes loading from different Entitys but now I have another problem: saving the dataform. The Commit and Cancel are even disabled. I've seen you post in forums.silverlight.net/…/392624.aspx and I have to ask you, should I create different DomainContext to my three DDS?

    Thank you.

  34. Marcel Marnix says:

    Hello Kyle,

    Can you help me to get a drop-down list being populated on the "linked" datagrid.

    Now only one item is showing in stead of a list, also I'll have to click three times to open the combobox, how can I get a list only clicking once? I've posted some code with this comment, I'll hope you can see it.

    I've created three tables, A person with a place(plaats) where he lives and a communication type(soort),  E-mail Fax or Phone.

    tblPersonen: Persoon_ID, Naam And Plaats

    tblCommunicaties: Communicatie_ID, Persoon_ID, CommunicatieSoort_ID, Communicatie

    tblCommunicatieSoorten: CommunicatieSoort_ID, CommunicatieSoort

    [html]<UserControl x:Class="SL4RIA_NAW.MainPage"

       xmlns="schemas.microsoft.com/…/presentation"

       xmlns:x="schemas.microsoft.com/…/xaml"

       xmlns:d="schemas.microsoft.com/…/2008"

       xmlns:mc="schemas.openxmlformats.org/…/2006"

       mc:Ignorable="d"

       d:DesignHeight="300"

       d:DesignWidth="500"

       xmlns:riaControls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.DomainServices"

       xmlns:srvApp="clr-namespace:SL4RIA_NAW.Web"

       xmlns:ex="clr-namespace:ComboBoxExtensions;assembly=ComboBoxExtensions"

       xmlns:sdk="schemas.microsoft.com/…/sdk">

       <UserControl.Resources>

           <srvApp:NAWDomainContext x:Key="NAWDomainContext"/>

           <ex:ComboBoxDataSource

               x:Key="cbddsCommunicatieSoorten"

               OperationName="GetTblCommunicatieSoortenQuery"

               DomainContext="{StaticResource NAWDomainContext}"/>

           <CollectionViewSource

               x:Key="tblPersonentblCommunicatiesViewSource"

               Source="{Binding Path=Data.tblCommunicaties, ElementName=tblPersonenDomainDataSource}" />

       </UserControl.Resources>

       <Grid x:Name="LayoutRoot" Background="White">

           <Grid.RowDefinitions>

               <RowDefinition Height="172*" />

               <RowDefinition Height="128*" />

           </Grid.RowDefinitions>

           <Grid.ColumnDefinitions>

               <ColumnDefinition Width="149" />

               <ColumnDefinition Width="268" />

               <ColumnDefinition Width="83*" />

           </Grid.ColumnDefinitions>

           <riaControls:DomainDataSource

               AutoLoad="True"

               d:DesignData="{d:DesignInstance srvApp:tblPersonen, CreateList=true}"

               Height="0"

               LoadedData="tblPersonenDomainDataSource_LoadedData"

               Name="tblPersonenDomainDataSource"

               QueryName="GetTblPersonenQuery" Width="0">

               <riaControls:DomainDataSource.DomainContext>

                   <srvApp:NAWDomainContext />

               </riaControls:DomainDataSource.DomainContext>

           </riaControls:DomainDataSource>

           <sdk:DataGrid AutoGenerateColumns="False"

                         ItemsSource="{Binding ElementName=tblPersonenDomainDataSource, Path=Data}"

                         Name="tblPersonenDataGrid"

                         RowDetailsVisibilityMode="VisibleWhenSelected" Margin="12,0,15,19">

               <sdk:DataGrid.Columns>

                   <sdk:DataGridTextColumn x:Name="naamColumn" Binding="{Binding Path=Naam}" Header="Naam" Width="SizeToHeader" />

                   <sdk:DataGridTextColumn x:Name="plaatsColumn" Binding="{Binding Path=Plaats}" Header="Plaats" Width="SizeToHeader" />

               </sdk:DataGrid.Columns>

           </sdk:DataGrid>

           <riaControls:DomainDataSource

               x:Name="ddsCommunicaties"

               QueryName="GetTblCommunicatieSoortenQuery"

               AutoLoad="True"

               DomainContext="{StaticResource NAWDomainContext}" Margin="0,0,302,218">

            </riaControls:DomainDataSource>

           <sdk:DataGrid

               x:Name="CommunicatiesDataGrid"

               ItemsSource="{Binding Source={StaticResource tblPersonentblCommunicatiesViewSource}}"

               AutoGenerateColumns="False" RowDetailsVisibilityMode="Visible" Grid.Column="1" Margin="0,0,16,19">

               <sdk:DataGrid.Columns>

                   <sdk:DataGridTextColumn

                       x:Name="communicatieColumn"

                       Binding="{Binding Path=Communicatie}"

                       Header="Communicatie"

                       Width="SizeToHeader" />

                   <sdk:DataGridTemplateColumn

                                   x:Name="cboSoortColumn"

                                   Header="Soort"

                                   Width="SizeToCells">

                       <sdk:DataGridTemplateColumn.CellTemplate>

                           <DataTemplate>

                               <TextBlock

                                   Text="{Binding Path=tblCommunicatieSoorten.CommunicatieSoort}"

                                   VerticalAlignment="Center"

                                   Padding="4" />

                           </DataTemplate>

                       </sdk:DataGridTemplateColumn.CellTemplate>

                       <sdk:DataGridTemplateColumn.CellEditingTemplate>

                           <DataTemplate>

                               <ComboBox

                                   x:Name="cboCommunicatieSoort"

                                   ItemsSource="{Binding Path=DataContext, Source={StaticResource cbddsCommunicatieSoorten}}"

                                   SelectedItem="{Binding Path=tblCommunicatieSoorten, Mode=TwoWay}"

                                   DisplayMemberPath="CommunicatieSoort"

                                   ex:ComboBox.Mode="AsyncEager"

                                />

                           </DataTemplate>

                       </sdk:DataGridTemplateColumn.CellEditingTemplate>

                   </sdk:DataGridTemplateColumn>  

               </sdk:DataGrid.Columns>

           </sdk:DataGrid>

       </Grid>

    </UserControl>

    [/html]

  35. kylemc says:

    @Bruno

    I'm afraid I might not understand you correctly. It sounds like You have a few dependent ComboBoxes in your DataForm. It also sounds like you're using DomainDataSources to fill them with data. I'd recommend you don't take that approach (as I mentioned in my first point above). It might be better to use a ComboBoxDataSource instead.

    To save data in your DataForm, you will need to submit it using the DomainContext where the entity you're editing was loaded. If you loaded the entity through a DomainDataSource, you can use it to submit the changes.

  36. kylemc says:

    @Marcel

    It looks like you're binding to the wrong property on the ComboBoxDataSource. It should be

    {Binding Path=Data, …} instead of

    {Binding Path=DataContext, …}

  37. Marcel Marnix says:

    @Kyle

    I started with data, doesn't that work either

  38. kylemc says:

    @Marcel

    If you want to send me you application, I can take a look. Here are some general thoughts on your problem.

    I'm not sure what you have to do to click once (instead of three times) to open a ComboBox. I'm pretty sure I've seen threads on it on the SL Forum, though. Take a look around.

    I think you'll only see a single item in the list when using AsyncEager selection when you already loaded the data source Data and it does not contain the item you've bound the SelectedItem to. In that case, the extension assumes the source will contain the item soon. Perhaps there's something selected that's not in the type list? Also, check to make sure the Data is populated at all. You could see this scenario if the list were empty.

  39. Marcel Marnix says:

    @Kyle

    Where can I sent the app?

  40. kylemc says:

    @Marcel

    Just use the 'Email Blog Author' link at the top. I'll email you back.

  41. Alexander G. Bykin says:

    Hi Kyle.

    i have suggestion:

    – can you please add "DataContext" for the Parameter of ComboBoxDataSource, it is necessary to use different sources of data in the parameters.

    thanks.

  42. Bruno says:

    Hi Kyle.

    I've finally putted my three combobox working fine. I've a Combobox to choose "Country", once you choose it the other combobox load the states from that country and once you choosed the state, I have another Combo that loads the citys. I've followed your sample and I'm passing parameters to three combos and all combos are from diferent entitys and it's all working perfectly.

    My question is, how can I save the data? "Country", "State" and "City" are diferent entitys and I want to save the data collected to another entity called "Address". Can you please help me? Thank you.

  43. kylemc says:

    @Alexander

    I'm not sure how easy that would be. I think you'd just have to make the Parameter (and possibly ParameterCollection) a FrameworkElement instead of a DependencyObject. Give it a try and let me know how it works.

    @Bruno

    It might be easiest if I could take a look at your application and make specific recommendations. To contact me, use the 'Email Blog Author' link at the top. I'll reply back so you can send me attachments, etc.

  44. Alexander G. Bykin says:

    Hi Kyle.

    i think i found small bug, try to clear Parameters from codebehind and you have exception 'Method is not implemented'.

    suggestion:

    can you please implement AutoLoad property and Load method for ComboBoxDomainDataSource like it have DomainDataSource?

    because when i try to add Parameters from codebehind i need:

    1) add parameters;

    2) load datasource;

    it can't be done and i have exception…

    thanks.

  45. kylemc says:

    @Alexander

    I included the source with the library so you could make any small tweaks or changes that your application needs. In this case, I haven't changed the source at all so the version you downloaded with the library is the latest.

  46. Doguhan Uluca says:

    Hey Kyle,

    I have to agree with David Zuber's post on 22 Jul 2010 12:46 AM. Your combobox is a life saver, but for some reason it prevents the metadata being loaded by the data form. So I won't get any properties I define through [Display()] on the server. And if I'm not auto generating my fields, you proposed solution doesn't work.

    Is there way to force a DataField to pick up the metadata somehow, something in the combobox extension that we can change, so that this data will appear.

    Thanks,

  47. Doguhan Uluca says:

    Kyle,

    One more addition, I actually tried your suggestion as well. It does not restore the metadata. As DataField Label it prints "SelectedItem" and the "!" icon for description doesn't appear.

    Thanks again.

  48. kylemc says:

    @Doguhan

    I think I've figured out why the metadata isn't propagated. I'll try to work up a solution in the next week. Stay tuned.

  49. Alexander G. Bykin says:

    Hey Kyle.

    If you need info how to get fields data from medata, look at my project where i implement that

    riadatafilter.codeplex.com/…/57649

    Method GetListOfDomainEntityFields.

    hope this helps, cheers.

  50. Doguhan Uluca says:

    Kyle,

    Any updates? I was hoping to roll out my app today.

  51. kylemc says:

    @Doguhan

    Not yet. I looked through the DataForm for hooks into the metadata, but couldn't find anything worthwhile. I have another thought (drawn on my whiteboard), but I'm not sure whether that will work either. How hard would it be to 'brute force' your metadata? You just have to set the DataField properties to the same strings. I'll keep working on this, but I'm not sure when I'll have an acceptable solution.

  52. duluca says:

    @Kyle

    I haven't thought of that. I tried it, it'll have to do for now. I hope your async combobox implementation makes it do the next official release.

    Doguhan

  53. kylemc says:

    @Doguhan

    Good news. I figured out a way to get the metadata to appear. In my sample I have:

    <df:DataField Label="A">…

    If you have metadata on the Entity type the combo box is binding to, just switch from specifying the Label to specifying the PropertyPath.

    <df:DataField PropertyPath="A">…

    This will pick up all your metadata correctly.

  54. Nathan says:

    Hello Kyle,

    I am new to Silverlight 4 with RIA Services.

    I have the same scenario as Bruno Lopes posted on 17th August (Country, State scenario)

    Problem is my app is able to show the right selected items on Country and State comboboxes but comboboxes do not show other items except the selected item when I tried to edit or change the selection on Country combobox.

    These comboboxes are inside the DataForm.

    Thanks for you Help!! 🙂

  55. Jandos says:

    It seems to me other controls such as AutoCompleteBox, List etc. which have ItemsSource property all have problem with RIA Services. At least, I can say that AutoCompleteBox behaves oddly.

  56. Reese says:

    Kyle,

    Thanks for you help on the Combobox.

    I have it working pretty well, but I'm having trouble requerying the data for the combobox.

    The data in the combobox is dynamic, and can be edited elsewhere in my application.  If I do edit the data that is to be displayed in the combobox, the combobox is not changed.

    I tried adding ComboBoxSource.Refresh() on the GotFocus event of the combobox.  That helps, in that it will refresh the collection to show newly added or newly deleted records.  But the Refresh() method doesn't show edits to the existing members of the collection.   Does that make sense?

    Do you have any ideas on how to proceed?

    Thanks,

    Reese

  57. bl8nc says:

    Here I have two combo boxes hooked up in code. Hope this might help someone.

    <telerik:RadComboBox Canvas.Left="773"  SelectedValuePath="SizeId" Canvas.Top="469" Width="189" x:Name="rdCmbBxSize" ItemsSource="{Binding}" >

    <telerik:RadComboBox.ItemTemplate>

                               <DataTemplate>

                                   <StackPanel>

                                       <StackPanel Orientation="Horizontal">

                                           <TextBlock Text="{Binding Name}" />

                                           <TextBlock Text="  (" />

                                           <TextBlock Text="{Binding StockStatus}" />

                                           <TextBlock Text=")" />

                                       </StackPanel>

                                   </StackPanel>

                               </DataTemplate>

                           </telerik:RadComboBox.ItemTemplate>

    </telerik:RadComboBox>

    <TextBlock Height="17" Canvas.Left="773" TextWrapping="Wrap" Text="Size" Canvas.Top="448" Width="189"/>

                       <telerik:RadComboBox Canvas.Left="773"  SelectedValuePath="ColorId"  Canvas.Top="516" Width="189" x:Name="rdCmbBxColor" ItemsSource="{Binding}" >

                           <telerik:RadComboBox.ItemTemplate>

                               <DataTemplate>

                                   <StackPanel>

                                       <StackPanel Orientation="Horizontal">

                                           <TextBlock Text="{Binding Name}" />

                                           <TextBlock Text="  (" />

                                           <TextBlock Text="{Binding StockStatus}" />

                                           <TextBlock Text=")" />

                                       </StackPanel>

                                   </StackPanel>

                               </DataTemplate>

                           </telerik:RadComboBox.ItemTemplate>

                       </telerik:RadComboBox>

    private void LoadSizesCombo(int productId)

           {

               this.ModalBusyIndicator.IsBusy = true;

               EntityQuery<SizesByStyle_Result> sizes = this.Context.GetSizesByStyleQuery(productId);

               this.Context.Load(sizes, (callback) =>

               {

                   if (callback.HasError)

                   {

                       this.ModalBusyIndicator.IsBusy = false;

                       ErrorWindow.CreateNew(callback.Error);

                       return;

                   }

                   this.rdCmbBxSize.ItemsSource = callback.Entities;

                   // get the first size

                   int sizeId = 0;

                   foreach( SizesByStyle_Result s in callback.Entities )

                   {

                       sizeId = s.SizeId;

                       break;

                   }

                   this.LoadColorsCombo(productId, sizeId);

                   this.rdCmbBxSize.SelectionChanged += new Telerik.Windows.Controls.SelectionChangedEventHandler(rdCmbBxSize_SelectionChanged);

                   this.rdCmbBxSize.SelectedIndex = 0;

               }, null);

           }

           void rdCmbBxSize_SelectionChanged(object sender, Telerik.Windows.Controls.SelectionChangedEventArgs e)

           {

               this.ModalBusyIndicator.IsBusy = true;

               LoadColorsCombo(this.productId, (int)this.rdCmbBxSize.SelectedValue);

           }

           private void LoadColorsCombo(int productId, int sizeId)

           {

               EntityQuery<ColorsByStyleAndSize_Result> sizes = this.Context.GetColorsByStyleAndSizeQuery(productId, sizeId);

               this.Context.Load(sizes, (callback) =>

               {

                   if (callback.HasError)

                   {

                       this.ModalBusyIndicator.IsBusy = false;

                       ErrorWindow.CreateNew(callback.Error);

                       return;

                   }

                   this.rdCmbBxColor.ItemsSource = callback.Entities;

                   this.rdCmbBxColor.SelectedIndex = 0;

                   this.ModalBusyIndicator.IsBusy = false;

               }, null);

           }

  58. John Lundy says:

    Telerik is third party is this still relevant?

  59. David Smith says:

    How do you use this in the DataForm.AutoGeneratingField event (code behind).

  60. kylemc says:

    @David Smith

    I assume you mean "How do you set the async mode?" It'll be something like this.

     ComboBoxExtensions.ComboBox.SetMode(myComboBox, CBE.CB.ComboBoxMode.Async);

  61. David Smith says:

    Thank you for all your hard work and timely response.

  62. Luka says:

    DataTemplate:

                                     <riaControls:DomainDataSource x:Name="ddsValues" QueryName="GetData_CompaniesQuery" DataContext="{Binding}">

                                           <riaControls:DomainDataSource.DomainContext>

                                               <my1:TicketingContext />

                                           </riaControls:DomainDataSource.DomainContext>

                                       </riaControls:DomainDataSource>

                                       <ComboBox ItemsSource="{Binding Data, ElementName=ddsValues}" SelectedValuePath="recCompanyID"  SelectedItem="{Binding SelectedItem, ElementName=data_CompaniesDataGrid, Mode=TwoWay}" DisplayMemberPath="CompanyName"  />

                                       <ex:ComboBoxDataSource Name="ASource" DomainContext="{StaticResource TicketingContext}" OperationName="GetData_CompaniesQuery" />

                                       <ComboBox Name="AComboBox" ItemsSource="{Binding Data, ElementName=ASource}"  SelectedValuePath="recCompanyID"  SelectedItem="{Binding SelectedItem, ElementName=data_CompaniesDataGrid, Mode=TwoWay}" DisplayMemberPath="CompanyName" ex:ComboBox.Mode="AsyncEager" />

    the second combobox…(the WRONG way to do this) is working fine.The selected item shows the correct member(but it doesn't change the value in the datasource when i select a different item in the combobox)…but the first combobox using your class isn't showing the selected item from the grid.selecteditem (looking at the source) is ALWAYS null.

    HELP HELP HELP.Wasted 2 days on this 🙂

  63. luka says:

    uh sorry…i meant to write the FIRST combobox…(the WRONG way to do this) is working fine.

  64. kylemc says:

    @Luka

    I don't know what using a SelectedValuePath with a SelectedItem binding does. I assume it doesn't work. Also, why would you want the item selected in your DataGrid to be the item selected in your ComboBox. I imagine you'd want to be setting the DataContext instead. Something along these lines (from the sample).

     <Grid Name="Form" DataContext="{Binding SelectedItem, ElementName=DataGrid}">

    Now everything within the Grid will use that DataContext in their bindings.

  65. Cleyton says:

    Hi,

    I had to add an Invoke attribute for the DomainContext to compile

    [Invoke]

           public IEnumerable<string> GetCountryStrings()

           {

              return new[] { "UK", "USA" };

           }

    The combo box is now filled in the data form. However the save method does not work.

    The new value is not saved to the database and when I refresh the page the comobox still shows the old value selected.

    I beliver that using Invokde attribute will stop change tracking.

    How can I get it to work?

    Cheers

    C

  66. Ajay says:

    Hello Kyle,

     I am following your example and implementing the combobox extensions in my problems. I am having some issues with the combobox not displaying any selected item when loading sometimes. I am using the comboxes in a view directly not inside a data form. I am copying the combobox code from the view. Can you please tell me where I am doing it wrong.

           <ex:ComboBoxDataSource Grid.Row="0" Grid.ColumnSpan="3" x:Name="ProjectsSource" DomainContext="{StaticResource TsDomainContext}" OperationName="GetProjectsQuery"></ex:ComboBoxDataSource>

           <ex:ComboBoxDataSource Grid.Row="0" Grid.ColumnSpan="3" x:Name="WorkTypesSource" DomainContext="{StaticResource TsDomainContext}" OperationName="GetWork_typesQuery"></ex:ComboBoxDataSource>

               <StackPanel Grid.Column="1" Grid.Row="1" Name="stackPanel2" Orientation="Vertical" UseLayoutRounding="True" BindingValidationError="stackPanel2_BindingValidationError">

               <ComboBox Height="25" ex:ComboBox.Mode="AsyncEager" Name="cboProject" ItemsSource="{Binding Data, ElementName=ProjectsSource}" SelectedValue="{Binding project_id, ValidatesOnExceptions=True, NotifyOnValidationError=True, Mode=TwoWay}" Width="261" Margin="5" FlowDirection="LeftToRight" HorizontalAlignment="Left" DisplayMemberPath="project_name" SelectedValuePath="project_id" SelectionChanged="cboProject_SelectionChanged" />

               <ComboBox Height="25" Name="cboWorkType" ex:ComboBox.Mode="AsyncEager" ItemsSource="{Binding Data, ElementName=WorkTypesSource}" SelectedValue="{Binding type_id, ValidatesOnExceptions=True, Mode=TwoWay, NotifyOnValidationError=True}" Width="261" Margin="5" FlowDirection="LeftToRight" HorizontalAlignment="Left" DisplayMemberPath="work_type1" SelectedValuePath="id" />

                   <TextBox Height="94" Name="txtMemo" LostFocus="txtCommon_LostFocus" Text="{Binding memo, Mode=TwoWay, ValidatesOnExceptions=True, NotifyOnValidationError=True}" Width="275" Margin="5" IsTabStop="True" FlowDirection="LeftToRight" HorizontalAlignment="Left" TextWrapping="Wrap" />

               </StackPanel>

    Thanks,

    Ajay.

  67. kylemc says:

    @Ajay

    Make sure you set the ex:ComboBox.Mode at the very end so it can correctly handle the bindings. Also, AsyncEager mode doesn't work when DisplayMemberPath is different from SelectedValuePath. You'll need to use plain Async mode instead (see this post for an explanation of the difference blogs.msdn.com/…/silverlight-combobox-frequently-asked-questions.aspx). If those changes don't fix it, feel free to email me using the 'Email Blog Author' link above.

  68. Ajay says:

    Thank you for the immediate response. Adding the ex:ComboBox.Mode at the very end did the trick it seems.  

    Thanks,

    Ajay.

  69. andrew says:

    Hi kylemc,

    thank you for your solution…

    Your code is working perfectly, but when I run your sample I have the following messages in the debug output window of Visual Studio:

    Could not find a method named GetBValues with the specified parameters ().

    Could not find a method named GetCValuesQuery with the specified parameters ().

    Could not find a method named GetBValues with the specified parameters ().

    Could not find a method named GetCValuesQuery with the specified parameters ().

    Do you know why? All the comboboxes are working correctly and the query are called…

    THANKS!

  70. Daniel Salazar says:

    Thanks Kyle! You really helped me!!!!! I was two work days trying to make it work.

  71. Jim says:

    Hi Kyle,

    I downloaded the sample from this link archive.msdn.microsoft.com/…/ProjectReleases.aspx and compilation passed but it crashed with the message "The provided URI scheme 'file' is invalid; expected 'http'. Parameter name: via"  Can you help?

  72. kylemc says:

    @Jim

    You need to set the 'Web' project as the startup project. The error you're seeing is caused by trying to run the Silverlight project.

  73. maria says:

    Hi,

    can i add this to silverlight 3 with VS2008 so i can work with my combobox?

    thanx so much..

  74. Kamil says:

    I am using static binding it works fine on dataform but when i use it in grid it works but after i scroll to next record i try to load it through code but is there any solution for this

  75. Almond says:

    Hello Kyle,

    I was able to run your Extension in a chid window, now my problem is that i am not able to save the new record that I created and also the record of which i editted.  What I am curious is what is that when I edit the a record, the changes reflects on the Grid but not on the database?  I am missing something here? Also when saving a record after creation, an error is being experienced in the with regards to the filterdescription declaration.

    Hope you can help me. It has been weeks and i can't go forward with my  project because of this issue 🙁

    Thanks in advance for the help

  76. Finally!!! says:

    at long last I have succesfully implemented Kyle's Extension… 🙂

    For those who needs help in implementing it using DDS and Static Context.  Just message me and I will be glad to help you in any way I can 🙂

    Again, much thanks Kyle 🙂

  77. Roger S says:

    Your sample; archive.msdn.microsoft.com/…/ProjectReleases.aspx

    This project doesn't run.

    The provided URI scheme 'file' is invalid; expected 'http'.

    Parameter name: via

  78. Roger Smith says:

    Ok, here is the challenge, as it seems everyone avoids it in every sample application I've seen.

    I have a database with only two tables.  The main table has foreign key to a lookup table.

    For example Employee table and Department table.

    The employee table has just the ID of the department table.

    The department table has the description of the dept – relational database 101.

    Simple simple as can be.

    Using RIA services I have a navigation page with a dataform to maintain details about the employee.  Instead of showing the Department ID (integer) to the user.  I simply want to show a combo box listing the items in the department table and for the selected item to be the employee's current dept.

    Now I feel a bit stupid posting this as I consider the request to be no more complex than a "Hello World" sample.

    However,  after six month of browsing sample after sample, tutorial after tutorial I am yet to find one demonstration of this concept.

    Why can I not find this?  I suspsect the answer is that Silverlight / Ria Services cannot do it. In which case it is next to usless.

    Please someone prove me wrong

  79. pedduri says:

    Kyle,

    In silverlight 5 how these issues are addressed ? i am eagerly waiting for the solution of combobox problems what you discussed aboove.

  80. Jack Webb says:

    I'm having a little trouble.  After weeks trying to get a ComboBox to work in a DataGrid,

    I finally made a break through using your sample.

    However, When in edit mode of a row, and I click the ComboBox,

    I get the entity that was there as the only selection.  

    I'm sure it's something to do with translating your ABC's to my real entity names,

    and would appreciate another set of eyes to have a look.

    Relevant excerpts from my View xaml:

           xmlns:my="clr-namespace:agmaTin.Web"

           xmlns:my2="clr-namespace:agmaTin.Views"

           xmlns:sdk="schemas.microsoft.com/…/sdk"

           xmlns:excb="clr-namespace:ComboBoxExtensions;assembly=ComboBoxExtensions"

           d:DesignWidth="865" d:DesignHeight="603"

           Title="Contractor Page"

           >

       <Grid x:Name="LayoutRoot" Width="Auto" Height="Auto">

           <UserControl>

               <UserControl.Resources>

                   <my:agmaTinDomainContext x:Key="agmaTinDomainContext" x:Name="agmaTinDomainContext"/>

               </UserControl.Resources>

           </UserControl>

           <ScrollViewer x:Name="PageScrollViewer" Style="{StaticResource PageScrollViewerStyle}" Margin="0,0,0,36">

               <StackPanel x:Name="ContentStackPanel" Style="{StaticResource ContentStackPanelStyle}" Width="Auto" Margin="0" HorizontalAlignment="Left" Height="Auto">

                   <TextBlock x:Name="HeaderText" Style="{StaticResource HeaderTextStyle}"

                      Text="{Binding Path=ApplicationStrings.ContractorPageTitle, Source={StaticResource ResourceWrapper}}"/>

                   <riaControls:DomainDataSource

                           AutoLoad="True"

                           d:DesignData="{d:DesignInstance my:QJob, CreateList=true}"

                           Height="0"

                           LoadedData="qJobDomainDataSource_LoadedData"

                           Name="qJobDomainDataSource"

                           QueryName="GetQJobsByContractorQuery"

                           Width="0"

                           LoadSize="40"

                           PageSize="20"

                       >

                       <riaControls:DomainDataSource.SortDescriptors>

                           <riaControls:SortDescriptor PropertyPath="Status" Direction="Ascending" />

                           <riaControls:SortDescriptor PropertyPath="Job_Number" Direction="Ascending" />

                       </riaControls:DomainDataSource.SortDescriptors>

                       <riaControls:DomainDataSource.DomainContext>

                           <my:agmaTinDomainContext/>

                       </riaControls:DomainDataSource.DomainContext>

                   </riaControls:DomainDataSource>

                   <excb:ComboBoxDataSource Name="OtherRequestSource" OperationName="GetOtherRequestsQuery">

                       <excb:ComboBoxDataSource.DomainContext>

                           <my:agmaTinDomainContext/>

                       </excb:ComboBoxDataSource.DomainContext>

                   </excb:ComboBoxDataSource>

    please note that the statements { <my:agmaTinDomainContext/> } have compile time error of

    { The type of my:agmaTinDomainContext was not found }

    continue excerpts:

    .

    .

    .

                       <sdk:DataGrid AutoGenerateColumns="False" Height="Auto" Name="qJobDataGrid" RowDetailsVisibilityMode="VisibleWhenSelected" Width="Auto" DataContext="{Binding}">

                           <sdk:DataGrid.Columns>

    .

    .

    .

                               <sdk:DataGridTemplateColumn x:Name="OtherRequestName" Header="Other Request" CanUserSort="True">

                                   <sdk:DataGridTemplateColumn.CellTemplate>

                                       <DataTemplate>

                                           <TextBlock Text="{Binding Path=OtherRequest.OtherRequestText}"/>

                                       </DataTemplate>

                                   </sdk:DataGridTemplateColumn.CellTemplate>

                                   <sdk:DataGridTemplateColumn.CellEditingTemplate>

                                       <DataTemplate>

                                           <ComboBox Name="cboOtherRequests" ItemsSource="{Binding Data, ElementName=OtherRequestSource}"

                                                     SelectedItem="{Binding Path=OtherRequest.OtherRequestText, Mode=TwoWay}"

                                                     excb:ComboBox.Mode="AsyncEager"/>

                                       </DataTemplate>

                                   </sdk:DataGridTemplateColumn.CellEditingTemplate>

                               </sdk:DataGridTemplateColumn>

    .

    .

    .

    The OtherRequest Table consists of two Columns: OtherRequestId and OtherRequestText

    The OtherRequest Table:

    OtherRequestId OtherRequestText

    1 none

    3 Suburban Rate

    4 Work Rules

    NULL NULL

    I have tried the ComboBox using all of (Default, Async, AsynchEager) modes with the same results.

    Any help would be most appreciated,

    Jack Webb

  81. kylemc says:

    @pedduri

    I haven't seen anything to make me think they added features to fix this.

    @Jack

    Take a look at the last section of this post (blogs.msdn.com/…/silverlight-combobox-frequently-asked-questions.aspx). The issue is almost always due to a mismatch between what you think is in the list and what actually is. For instance, it's important that you use the same DomainContext instance for both DataSources.

  82. Jack Webb says:

    Kyle, thanks for helping.

    I had a look at what I thought was the last post, and gleaned that I need to use Static Resources.

    So I put together what I think is the adaptation of creating a Static Resource as shown below.

    And in code behind I verified DomainContext equality between my DomainDataSource and my ComboBoxDataSource.

    But after compiling, my ComboBox in the DataGrid has an error of: The Resource "otherRequestDataSource" could not be resolved.

    Any thoughts?

    Attached xaml:

           <navigation:Page>

               <navigation:Page.Resources>

                   <web:agmaTinDomainContext x:Key="agmaTinDomainContext"/>

                   <dds:DomainDataSource AutoLoad="True" d:DesignData="{d:DesignInstance my:QJob, CreateList=true}"

                           Height="0" LoadedData="qJobDomainDataSource_LoadedData" x:Name="qJobDomainDataSource"

                           QueryName="GetQJobsByContractorQuery" Width="0" LoadSize="40" PageSize="20"

                           DomainContext="{StaticResource agmaTinDomainContext}">

                       <dds:DomainDataSource.SortDescriptors>

                           <dds:SortDescriptor PropertyPath="Status" Direction="Ascending" />

                           <dds:SortDescriptor PropertyPath="Job_Number" Direction="Ascending" />

                       </dds:DomainDataSource.SortDescriptors>

                   </dds:DomainDataSource>

                   <ex:ComboBoxDataSource x:Name="otherRequestDataSource" OperationName="GetOtherRequestsQuery"

                                          DomainContext="{StaticResource agmaTinDomainContext}"/>

               </navigation:Page.Resources>

           </navigation:Page>

                               <sdk:DataGridTemplateColumn x:Name="OtherRequestName" Header="Other Request" CanUserSort="True">

                                   <sdk:DataGridTemplateColumn.CellTemplate>

                                       <DataTemplate>

                                           <TextBlock Text="{Binding Path=OtherRequest.OtherRequestText}"/>

                                       </DataTemplate>

                                   </sdk:DataGridTemplateColumn.CellTemplate>

                                   <sdk:DataGridTemplateColumn.CellEditingTemplate>

                                       <DataTemplate>

                                           <ComboBox Name="cboOtherRequests"

                                                     ItemsSource="{Binding Data, Source={StaticResource otherRequestDataSource}}"

                                                     SelectedItem="{Binding OtherRequest, Mode=TwoWay}"

                                                     ex:ComboBox.Mode="Async"/>

                                       </DataTemplate>

                                   </sdk:DataGridTemplateColumn.CellEditingTemplate>

                               </sdk:DataGridTemplateColumn>

  83. kylemc says:

    @Jack

    The code here looks correct to me. I'm not sure what the issue is. Sorry I don't have more insight.

  84. Darren says:

    Hi Kyle, thanks for the great code.  I just have one question: is it possible to reload the data from the web service via code?  I have a ComboBox in a DataForm displaying a list of items, and next to this a button which opens a modal dialog to allow editing of this list. When the dialog closes, changes are submitted to the database, but not reflected in the ComboBox.

    I've tried getting the ComboBoxDataSource (var ds = (ComboBoxDataSource)this.myEditForm.FindNameInContent("MyCBDataSource"); ) and calling ds.Refresh(), but this doesn't seem to do anything.  With a DomainContext I'd call ctx.Load(), but there's no Load method on the ComboBoxDataSource.

    Can you help me out?

  85. kylemc says:

    @Darren

    If you want an editable list, then maybe using the CBDS isn't the best approach. You can always just set comboBox.ItemsSource explicitly in your code. For instance, maybe you could populate it initially with the result of ctx.Load() and then update it as the list is edited. An EntityList might work well in this scenario (take a look at this post to learn about EntityLists blogs.msdn.com/…/collection-binding-options-in-wcf-ria-services-sp1.aspx).

  86. Ankur Mittal says:

    Hi,

    Thanks a lot for your nice work,

    I am using Ria Services and i need some cascading Combo boxes. I use your combobox extension liabrary. First combo ,works perfectly, and with hard coded parameters other combo also work. But when i take parameter values from combo 1, it does'nt work.

    Means, First time all combo calls their respective data methods but on selection change of combo box 1 doesnt fire the data populate methods of dependant combos. Am i missing something???

    Please help,

    Thanks in advance,

  87. Almond says:

    Hello Kyle,

    It seems that my previous posts didnt went through.  

    Hope you can again help me with my concern. I would just like to select the first record of the combobox after a Selection changed was done in the the main combo box. For example i have 3 tables as follows: company, department and section. If the company combobox changes only the selected records related to that company will be loaded in the departmentCbo.  I have successfully implemented it however i still need to click the departmentCbo in order for me to see the records. Is it possible to select and display the 1st Record of the filtered departmentCbo based on the companyCbo.

    By the way, i have successfully implemented that same selection process if the combobox is outside a dataform. I used the LoadCompleted event of the ex:ComboBoxDataSource and from the LoadCompleted code behind I then execute the departmentCbo SelectedIndex = 0; command.

    I really hope you can point me what I am doing wrong.

    Thanks in advance once again.

    Almond

  88. casey says:

    Can you tell me what I'm missing…. I have an AGENCY table and DEPARTMENT table yet when displaying AGENCY  i cant see DEPARTMENT.name.. I see it DEPARTMENT table listed in my AGENCY metadata.. But why can't i see DEPARTMENT.name.. Please any help would be great.. I am trying to get this solution to work because I'm having weird dataform/multi combobox issues (where it saves the first time but not the second)

    Thank you in advance

  89. Dylan Jones says:

    Do you have an example where you are using SelectValue=Binding Path="….."  or SelectedItem="….."

    Thanks

  90. Shenbagaraj says:

    When i try this im facing an error " Set property 'RiaServicesContrib.ComboBoxExtensions.ComboBox.Mode' threw an exception."  help me out plz i, not using datasource .

  91. Kyle – you mention at the conclusion of this article that you hope the combobox issues will be addressed in SL5.  Do you think that's the case?  I'm beginning development with v5 now and I wonder if I still need to use the customdatasource or if I should go back to the dds.   -Thanks, Mark

  92. kylemc says:

    @MarkAArnold

    I do not think the issues I mentioned were fixed in SL5, but I haven't verified either way. I'd recommend sticking with the custom DS.

  93. @casey says:

    were you able to fix your problem?

  94. Almond says:

    @ Casey

    were you able to fix your problem with regards to the Agency and Department problem?

    Sorry for the late reply.

Skip to main content