Reputation: 2626
I'm trying to include a ComboBox column in a WPF datagrid. I'm trying to bind this column to an observable collection in the ViewModel however, at run time the cells remain empty. Datacontext is correct, as all normal columns bind successfully. I want to display 'regionShortCode' in the UI. Here's my xaml:
<DataGridComboBoxColumn Header="Region" DisplayMemberPath="regionShortCode" Width="SizeToHeader">
<DataGridComboBoxColumn.ElementStyle>
<Style>
<Setter Property="ComboBox.ItemsSource" Value="{Binding Path=MembershipsCollection}" />
</Style>
</DataGridComboBoxColumn.ElementStyle>
<DataGridComboBoxColumn.EditingElementStyle>
<Style>
<Setter Property="ComboBox.ItemsSource" Value="{Binding Path=MembershipsCollection}" />
</Style>
</DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>
& here is my ObservableCollection declared in the ViewModel. The Collection is populated successfully from a method invoked in the constructor:
private ObservableCollection<tbAccountMembership> _MembershipsCollection;
public ObservableCollection<tbAccountMembership> MembershipsCollection
{
get { return _MembershipsCollection; }
set
{
_MembershipsCollection = value;
OnPropertyChanged("MembershipsCollection");
}
}
At run time I get:
System.Windows.Data Error: 40 : BindingExpression path error: 'MembershipsCollection' property not found on 'object' ''tbAccountMembership_041E43AFC29975F12C156BA1373ACD47FC07BBE55614E5AF8AD3BBD9F090C133' (HashCode=46247020)'. BindingExpression:Path=MembershipsCollection; DataItem='tbAccountMembership_041E43AFC29975F12C156BA1373ACD47FC07BBE55614E5AF8AD3BBD9F090C133' (HashCode=46247020); target element is 'TextBlockComboBox' (Name=''); target property is 'ItemsSource' (type 'IEnumerable')
in the Output window. Why can't the Xaml resolve this binding? Thanks
Upvotes: 1
Views: 9837
Reputation: 9827
A much easier solution with DataGridComboBoxColumn is to set ItemSource binding programmatically in Window class' constructor.
<DataGrid x:Name="MembershipGridNormal" AutoGenerateColumns="False" SelectedIndex="0" ItemsSource="{Binding}">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding Prop1}"/>
<DataGridTextColumn Header="Value" Binding="{Binding Prop2}"/>
<DataGridComboBoxColumn x:Name="CmbMemberShips" Header="RawValues" DisplayMemberPath="Name" />
</DataGrid.Columns>
</DataGrid>
in code behind
public Win32599087()
{
InitializeComponent();
MemberShipGridNormal.DataContext = myCollection;
Binding b = new Binding();
b.Source = myCollection;
b.Path = new PropertyPath("collectionpropertyname");
BindingOperations.SetBinding(CmbMemberships, DataGridComboBoxColumn.ItemsSourceProperty, b);
}
Upvotes: -1
Reputation: 335
You have to provide exact path to the collection to bind with the itemssource of the combobox. for this make your ancestor as your main control i.e window or the usercontrol
<DataGridComboBoxColumn Header="Category"
SelectedValueBinding="{Binding category_cde}"
SelectedValuePath="category_cde"
DisplayMemberPath="category_dsc">
<DataGridComboBoxColumn.ElementStyle>
<Style TargetType="ComboBox">
<Setter Property="ItemsSource" Value="{Binding Path=CATEGORIES , RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" />
</Style>
</DataGridComboBoxColumn.ElementStyle>
<DataGridComboBoxColumn.EditingElementStyle>
<Style TargetType="ComboBox">
<Setter Property="ItemsSource" Value="{Binding Path=CATEGORIES , RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" />
</Style>
</DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>
</DataGrid.Columns>
</DataGrid>
And here is the collection of categories i defined in code behind where category is some class you can define your own collection
List<Category> m_categories = new List<Category>();
public List<Category> CATEGORIES
{
get { return m_categories; }
set { m_categories = value; }
}
Upvotes: 1
Reputation: 69959
If you want to data bind to a single collection property in the view model from the DataGrid
, then your answer to Why can't the Xaml resolve this binding? is because you didn't tell the Framework where to look for the actual property... you'll need to use a [RelativeSource Binding
]1. Try this instead:
<DataGridComboBoxColumn Header="Region" DisplayMemberPath="regionShortCode"
Width="SizeToHeader">
<DataGridComboBoxColumn.ElementStyle>
<Style>
<Setter Property="ComboBox.ItemsSource" Value="{Binding
DataContext.MembershipsCollection, RelativeSource={RelativeSource
AncestorType={x:Type YourViewModelsPrefix:YourViewModel}}}" />
</Style>
</DataGridComboBoxColumn.ElementStyle>
<DataGridComboBoxColumn.EditingElementStyle>
<Style>
<Setter Property="ComboBox.ItemsSource" Value="{Binding
DataContext.MembershipsCollection, RelativeSource={RelativeSource
AncestorType={x:Type YourViewsPrefix:YourView}}}" />
</Style>
</DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>
With this Binding Path
, the Framework will look outside of the normal DataGrid.DataContext
for a property named MembershipsCollection
in the object that is set as the DataContext
of the YourView
(clearly this is not the actual name) UserControl
or Window
. If y our view model is correctly set as the DataContext
then this should work just fine.
Upvotes: 1