I am working on my first ‘production’ WPF app, and I’m encountering an issue.
I have some code that is similar to the example below. The problem I am having is that I cannot get the ComboBox to populate. I’m assuming it is because the Grid‘s ItemsSource is ‘blocking’ the ComboBoxfrom being able to see the Tasks collection on the ViewModel, but I am only guessing. Everything else is databinding correctly.
I scoured SO and found this question; which sounds exactly like what I am trying to do, but it did not work for me.
Any idea why I can’t get the ComboBox to populate?
Model:
public class Activity{
public int Id { get; set; }
public string Title { get; set; }
public Task Task { get; set; }
}
public class Task{
public int Id { get; set; }
public string Title { get; set; }
}
ViewModel:
public ApprovalViewModel{
public ObservableCollection<Activity> Activities { /* ... property logic */ }
public ObservableCollection<Task> Tasks { /* ... property logic */ }
}
View:
<DataGrid ItemsSource="{Binding Activities}" AutoGenerateColumns="False">
<DataGrid.Resources>
<DataTemplate x:Key="displayTemplate">
<TextBlock Text="{Binding Task.Title}"/>
</DataTemplate>
<DataTemplate x:Key="editTemplate">
<ComboBox ItemsSource="{Binding Tasks}" <!--I think the problem is here-->
SelectedValue="{Binding Task}"
DisplayMemberPath="Title"/>
</DataTemplate>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridComboBoxColumn DisplayMemberPath="Title"/>
<DataGridTextColumn Binding="{Binding User}" Header="User"/>
<DataGridTextColumn Binding="{Binding Task.Project.Title}" Header="Project"/>
<DataGridTemplateColumn
Header="Task"
CellTemplate="{StaticResource displayTemplate}"
CellEditingTemplate="{StaticResource editTemplate}"/>
<DataGridTextColumn Binding="{Binding Description}" Header="Description"/>
</DataGrid.Columns>
</DataGrid>
Edit: the correct ComboBox code is here:
<ComboBox
ItemsSource="{Binding Path=DataContext.Tasks,
RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type UserControl}}}"
SelectedValue="{Binding Task.Title}"
SelectedValuePath="Title"
DisplayMemberPath="Title"/>
You are correct in where the problem lies, that binding is relative to the
Activity. So it is looking forActivity.Tasks.The post you linked to has the right approach, you just need to tweak it for your situation.
This will go back up the Visual tree looking for a Window, which has a
DataContext.Tasksproperty.Is your code example inside a window? If not you will need to change the {x:Type } and secondly is the
DataContextset on this object? If not you will need to set it to your ViewModel.