Binding to a WPF ComboBox

Posts   
 
    
Jack
User
Posts: 11
Joined: 31-Oct-2007
# Posted on: 05-Feb-2008 02:35:11   

I was wondering if someone could give a simple example of how to bind a an EntityView2 to a WPF ComboBox.

I have no problems binding to listviews or the xceed wpf datagrid but I have great difficulty binding to a combobox, getting the ambiguous error: "value isn't of the correct type":

System.ArgumentException was unhandled Message="value isn't of the correct type." Source="SD.LLBLGen.Pro.ORMSupportClasses.NET20" StackTrace: at SD.LLBLGen.Pro.ORMSupportClasses.EntityViewBase`1.System.Collections.IList.IndexOf(Object value) at System.Windows.Data.BindingListCollectionView.InternalIndexOf(Object item) at System.Windows.Data.BindingListCollectionView.IndexOf(Object item) at System.Windows.Controls.ItemCollection.IndexOf(Object item) at System.Windows.Controls.ItemsControl.NavigateToItem(Object item, Int32 elementIndex, ItemNavigateArgs itemNavigateArgs, Boolean alwaysAtTopOfViewport) at System.Windows.Controls.ComboBox.<OnIsDropDownOpenChanged>b__1(Object arg) at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Boolean isSingleParameter) at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler) at System.Windows.Threading.DispatcherOperation.InvokeImpl() at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state) at System.Threading.ExecutionContext.runTryCode(Object userData) at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Windows.Threading.DispatcherOperation.Invoke() at System.Windows.Threading.Dispatcher.ProcessQueue()

I assume the combobox is trying to find the index of a particular item within the collection, but instead of using the SelectedValuePath, it's attempting to pass in a string.

Snipets follow: <UserControl.Resources> <CollectionViewSource x:Key="cvsCountries" Source="{Binding Path=Countries}"> <CollectionViewSource.SortDescriptions> <scm:SortDescription PropertyName="DisplayName" Direction="Ascending"/> </CollectionViewSource.SortDescriptions> </CollectionViewSource> </UserControl.Resources>

                <ComboBox x:Name="cmbPostalCountry" Grid.Row="4" Grid.Column="1" ItemsSource="{Binding Source={StaticResource cvsCountries}}" DisplayMemberPath="DisplayName" SelectedValuePath="IsoCode" SelectedValue="{Binding Path=PhysicalCountryIsoCode}" />

The DataContext of the view has been set to a ContactEntity with one of it's properties being: PhysicalCountryIsoCode, which has a fk relationship with Country on IsoCode

Countries is an EntityView2 of CountryEntity which has the corresponding properties listed above: DisplayName IsoCode

Any help or suggestions, or even a simple example of an entity with an fk relationship being displayed within a combobox in wpf would be greatly appreciated.

Walaa avatar
Walaa
Support Team
Posts: 14994
Joined: 21-Aug-2005
# Posted on: 05-Feb-2008 10:35:33   

Does any of the envolved entities participate in an Inheritance hierarchy?

The error occurs where it can't cast the object passed in to the generic type argument of the view ('T') . Check the following MSDN link: http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2263277&SiteID=1

Jack
User
Posts: 11
Joined: 31-Oct-2007
# Posted on: 05-Feb-2008 15:30:24   

Thanks for the link, but I have already looked at it earlier today.

Perhaps I shouldn't have used the word ambiguous, due to the fact that there is an error as you have described which uses that particular word.

Neither entity participates in an inheritance hierarchy. I'm hoping I'm just missing something really simple and hence the reason why I asked for a simple databinding example, though if anyone knows what the cause of my error was (whether it is my own lack of understanding or what as I'm fairly new to wpf and llblgenpro)

I am also trying to work out best practice in the process as well, whether I should use the WPF CollectionViewSource, or just bind to an EntityView2 directly, and whether I should bind the CollectionViewSource to an EntityView2 or EntityCollection.

goose avatar
goose
User
Posts: 392
Joined: 06-Aug-2007
# Posted on: 05-Feb-2008 15:52:51   

You can find the example you're looking for in the examples section of the main site (http://llblgen.com/pages/examples.aspx)

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39883
Joined: 17-Aug-2003
# Posted on: 05-Feb-2008 16:47:30   

The direct source of the error is that an object is passed in to the IndexOf method which isn't castable to the generic type of the entityview.

Say you have an EntityCollection<CustomerEntity> and you bind that to the combobox. The IndexOf method of the EntityView2 created of the entity collection now gets an object passed in which isn't castable to CustomerEntity and it then gives this error.

It's rather strange though...

Frans Bouma | Lead developer LLBLGen Pro
Jack
User
Posts: 11
Joined: 31-Oct-2007
# Posted on: 06-Feb-2008 23:31:25   

I couldn't manage to find the wpf example on the examples page, they all seemed to be winforms or asp.net examples.

I have binding working fine for comboboxes when there is a value stored within the entity already, just seems to be playing up when the value is empty. In the above example I have a string as the key.

Walaa avatar
Walaa
Support Team
Posts: 14994
Joined: 21-Aug-2005
# Posted on: 07-Feb-2008 09:12:07   

I couldn't manage to find the wpf example on the examples page, they all seemed to be winforms or asp.net examples.

There is no WPF example there, only .NET 2.0 databinding examples.

I have binding working fine for comboboxes when there is a value stored within the entity already, just seems to be playing up when the value is empty. In the above example I have a string as the key.

What do you mean by a value stored? Do you mean value for the PK of the entity? DOes this mean that the binding is not working if you have new empty entities in the bound collection?

Jack
User
Posts: 11
Joined: 31-Oct-2007
# Posted on: 07-Feb-2008 12:28:35   

I mentioned the wpf example as it was one of the suggestions above that there was one on the examples page.

I set the DataContext of my usercontrol to a single Entity. eg. Contact

I set the ItemsSource of my ComboBox to an EntityView2 collection of other entities. eg. Countries

The property I am trying to bind to on the Contact is CountryIsoCode, it having an fk relation with Country.

If Contact already has a value for it's CountryIsoCode, binding works fine, I can choose another country from the list and it will bind correctly to the Contact. However if there is no value stored within CountryIsoCode, and I attempt to click on the ComboBox in order to choose a country I get the exception listed above.

The value stored refers to Contact.CountryIsoCode The binding is not working if there is no value stored within Contact.CountryIsoCode

Jack
User
Posts: 11
Joined: 31-Oct-2007
# Posted on: 07-Feb-2008 13:19:09   

Here is a good example of what I am trying to do: http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2580058&SiteID=1

In my example it's essentially the same except I am binding to an EntityView2 of CountryEntity instead of a datatable and am setting the DataContext to a ContactEntity.

Walaa avatar
Walaa
Support Team
Posts: 14994
Joined: 21-Aug-2005
# Posted on: 07-Feb-2008 15:06:07   

IMHO, that's not an LLBLGen Pro issue. I don't have much experience with WPF but I think this issue can occur in ASP.NET 2.0 binding, as your bound collection doesn't have an entity or (an empty item) which has null value for the PK to be selected in case the SelectedValue was null.

You should look for a way to insert an empty entry that qaulifies for the null PK, I don't know if you can do this with XAML, I guess you can since this was available in ASPX code .

Anyway I found this article for solving a similar issue.

Jack
User
Posts: 11
Joined: 31-Oct-2007
# Posted on: 08-Feb-2008 03:02:06   

Thanks for everyone's contributions.

The issue for future reference is as pointed out earlier due to the fact that WPF databinding is attempting to find a record in the collection corresponding to a null value.

What is needed in this scenario is 2 things: 1. Add an empty/'null' entity to the collection for the null value to correspond to, this enables you to display the null value correctly. (If there is no such entity in the collection, your combobox will appear to display properly, but when you attempt to change the value it will throw the exception I described in my first post.)

  1. Add a value converter to your binding to enable you to display a null value, and also enable a null value to be stored in the database as appropriate. (If this isn't present you will end up with possible foreign key violations/invalid data being entered into the database)

So a common example would be:

public class GuidConverter: IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value == null)
            return Guid.Empty;
        else return value;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value is Guid && (Guid)value == Guid.Empty)
            return null;
        else return value;
    }
}

I hope this post is useful to anyone who has similar problems.

Walaa avatar
Walaa
Support Team
Posts: 14994
Joined: 21-Aug-2005
# Posted on: 08-Feb-2008 09:44:42   

Thanks for the feedback.