Search code examples
wpfentity-framework-4collectionviewsource

An unhandled exception when using FirstOrDefault() with CollectionViewSource?


I bound entities to a CollectionViewSource. Then I query in code behind. Because the id field is the PK so I think I should use FirstOrDefault() to make my app execute faster. But it always throws an exception ...

XAML :

<Window.Resources>
        <CollectionViewSource x:Key="contractlogoesViewSource" d:DesignSource="{d:DesignInstance my:contractlogo, CreateList=True}" />
    </Window.Resources>
    <Grid>
        <Grid DataContext="{StaticResource contractlogoesViewSource}" HorizontalAlignment="Left" Margin="12,12,0,0" Name="grid1" VerticalAlignment="Top">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="Auto" />
            </Grid.ColumnDefinitions>
...

Code behind :

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    VBDAdvertisement.vbdadvertisementEntities vbdadvertisementEntities = new VBDAdvertisement.vbdadvertisementEntities();            
    System.Windows.Data.CollectionViewSource contractlogoesViewSource = ((System.Windows.Data.CollectionViewSource)(this.FindResource("contractlogoesViewSource")));
    contractlogoesViewSource.Source = vbdadvertisementEntities.contractlogoes.Where(q => q.id.Equals(3)).FirstOrDefault();
}

It throws an An unhandled exception :

An unhandled exception of type 'System.ArgumentException' occurred in
PresentationFramework.dll
Additional information: 'VBDAdvertisement.customer' is not a valid value for
property 'Source'.

But when I omit FirstOrDefault() from the expression tree, like this :

contractlogoesViewSource.Source = vbdadvertisementEntities.contractlogoes.Where(q => q.id.Equals(3));

It works well !

So why does FirstOrDefault() cause an error ?
Is this case, should I use FirstOrDefault(), will my app execute faster if I use FirstOrDefault() ?

ps : I am designing an edit form so I just want a single item to be loaded.


Solution

  • The reason you're getting the error is that you can't assign a single item to a CollectionViewSource. If it's an edit form, you probably don't need a CollectionViewSource and could bind to the item directly.

    If you do this you can use FirstorDefault() to get the first item. But in your case since your selecting by the ID, I think it's better to use SingleOrDefault() since it more accurately shows the intention of what you want, like so:

    contractlogoesViewSource.Source = vbdadvertisementEntities.contractlogoes.SingleOrDefault(q => q.id.Equals(3));
    

    SingleOrDefault() will throw an exception if more than one item matches the predicate, but since ID is the primary key that's not going to be a problem for you.

    If you want to use a CollectionViewSource (but I can't see why), you can use .Take() to get a collection containing a single item, like so:

    vbdadvertisementEntities.contractlogoes.Where(q => q.id.Equals(3)).Take(1);