Context: I am using EF 5 and trying to bind two entities to a WPF form. It works fine with simples property-to-textbox binding, but I’d like to bind a navigation property object to a combobox. I am learning WPF so this may be obvious.
I have two EF entities:
Product { int Id, string Name, Category Category }
and
Category { int Id, string Description }
I made a WPF form to create and edit products, it is something like this (simplified):
<Window.Resources>
<CollectionViewSource x:Key="productViewSource" d:DesignSource="{d:DesignInstance my:product, CreateList=True}" />
<CollectionViewSource x:Key="categoryViewSource" d:DesignSource="{d:DesignInstance my:category, CreateList=True}" />
</Window.Resources>
<Grid DataContext="{StaticResource productViewSource}">
<Label Content="Id" Height="28" HorizontalAlignment="Left" Margin="6,6,0,0" Name="label1" VerticalAlignment="Top" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="61,8,0,0" Name="txtId" Text="{Binding Path=Id, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" VerticalAlignment="Top" Width="56" IsEnabled="False" />
<Label Content="Name" Height="28" HorizontalAlignment="Left" Margin="6,38,0,0" Name="label2" VerticalAlignment="Top" />
<TextBox Text="{Binding Path=Name, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" Height="23" HorizontalAlignment="Left" Margin="61,40,0,0" Name="txtNome" VerticalAlignment="Top" Width="183" IsEnabled="False" />
<Label Content="Category" Height="28" HorizontalAlignment="Left" Margin="6,129,0,0" Name="label5" VerticalAlignment="Top" />
<ComboBox Height="23" HorizontalAlignment="Left" Margin="72,132,0,0" Name="comboCategory" VerticalAlignment="Top" Width="172"
DisplayMemberPath="Description"
SelectedValuePath="Id"
SelectedValue="{Binding Path=Category, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
ItemsSource="{Binding Path=categoryViewSource, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}">
</ComboBox>
</Grid>
The code to load the two View Sources is this:
private void Window_Loaded(object sender, RoutedEventArgs e)
{
context = new DBEntities();
var productViewSource = ((System.Windows.Data.CollectionViewSource)(this.FindResource("productViewSource")));
context.Product.Include(p => p.Category);
context.Product.Load();
ProductViewSource.Source = context.Product.Local;
var categoryViewSource = ((System.Windows.Data.CollectionViewSource)(this.FindResource("categoryViewSource")));
categoryViewSource.Source = context.Category.ToList();
}
When the window loads the two textboxes work, but the combobox is always empty.
Probally this is what is wrong, but I can’t seem to find a way to make it work.
ItemsSource="{Binding Path=categoryViewSource, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}"
This is wrong:
ItemsSource="{Binding Path=categoryViewSource, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}">What you’re telling WPF here is that you want the Property
categoryViewSourcefrom the firstWindowit encounters upwards in the Visual Tree. Of course theWindowClass doesn’t have such property.It should be:
ItemsSource="{StaticResource categoryViewSource}">which tells WPF you want to look up a Resource with that name (key)
Edit: You’d better create a ViewModel to hold your data:
XAML:
Remove the Static Resources and remove all references to them.
Edit 2:
The
SelectedValuePathAndSelectedValueProperties work together. TheSelectedValuePathis telling the ComboBox “Evaluate this property inside each item”, and theSelectedValueproperty is the actual value you expect to find in that property, so:Is telling WPF that you have some
intproperty calledCategoryin your DataContext class which you expect to contain a value matching theIdof one of your entities.What you actually need to do here is:
ViewModel:
XAML:
and remove both SelectedValuePath and SelectedValue.