DataGridComboBoxColumn binding issue - wpf

I have DataGridComboBoxColumn in DataGrid:
<DataGridComboBoxColumn Header="{x:Static Properties:Resources.Unit}" Width="Auto"
SelectedValueBinding="{Binding UnitUnitId}"
SelectedValuePath="UnitId"
DisplayMemberPath="Name" >
<DataGridComboBoxColumn.ElementStyle>
<Style TargetType="ComboBox">
<Setter Property="ItemsSource" Value="{Binding Path=DataContext.Units,RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"/>
</Style>
</DataGridComboBoxColumn.ElementStyle>
<DataGridComboBoxColumn.EditingElementStyle>
<Style TargetType="ComboBox">
<Setter Property="ItemsSource" Value="{Binding Path=DataContext.Units,RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"/>
</Style>
</DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>
and ComboBox:
<ComboBox x:Name="unitBox" ItemsSource="{Binding Path=Units}"
SelectedItem="{Binding TaxSubGroup.Unit}"
Grid.Row="2"
Grid.Column="1" Margin="11,11,0,0" HorizontalAlignment="Stretch">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Converter={x:Static c:UnitToStringConverter.Default}}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Units property:
public ObservableCollection<Unit> Units
{
get
{
return _units;
}
set
{
if(_units!=value)
{
_units = value;
RaisePropertyChanged("Units");
}
}
}
when i'm changing ComboBoxes value, DataGridComboBoxColumn's value updating automatically, but changing DataGrid's comboboxcolumn's value not updating ComboBoxes value. Why?
UPDATED
The problem was in DataGridComboBoxCulumn's SelectedValueBinding property. All i needed is to add UpdateSourceTrigger property:
SelectedValueBinding="{Binding UnitUnitId,UpdateSourceTrigger=PropertyChanged}"

Are you updating TaxSubGroup.Unit in the setter of UnitUnitId property?
In your DataContext model class do something similar to this...
public int UnitUnitId
{
get
{
return this.unitID;
}
set
{
this.unitID = value;
this.TaxSubGroup.Unit = Units.FirstOrDefault(u => u.UnitID == value);
this.NotifyPropertyChange("UnitUnitId");
}
}
This will match SelectedItem of Combobox by reference.

Related

WPF Hide an Item of a Combobox ItemSource

In my WPF View, I have a DataGrid which Display Data from a Database.
One column is a combobox that is bound to a string in Database.
This is the list of available string :
public List<string> AvailableTypeImpression { get; } = new List<string>() {"S","D","T","X","M","p","P","R"}
All these string could be displayed in the datagrid, but if the user want to edit it, I can only set S, D, T, or X. The user is not allowed to set M, p, P or R.
So I would like to hide these four letter from the combobox available Items. But I don't really know how to do that in a simple way (I found some solution on Stack Overflow but it doesn't work in my case).
Here's the code of my datagrid :
<DataGrid Grid.Row="1" x:Name="LotsListDataGrid" IsReadOnly="False" SelectionMode="Single" SelectionUnit="FullRow" SelectedItem="{Binding SelectedLot}" ItemsSource="{Binding FilteredList}" VirtualizingPanel.IsVirtualizing="True" EnableRowVirtualization="True" HorizontalScrollBarVisibility="Auto">
<DataGrid.Columns>
<DataGridTextColumn Header="Lot" Width="200" Binding="{Binding Value.Lot.Intitule}" IsReadOnly="True"/>
<DataGridTemplateColumn Header=".i." HeaderStyle="{StaticResource CenteredColumnHeaderStyle}" Width="545" IsReadOnly="False">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox Height="23" Style="{StaticResource AnfComboBoxStyle}" ItemsSource="{Binding DataContext.AvailableTypeImpression, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}" SelectedItem="{Binding Value.Lot.TypeImpression, UpdateSourceTrigger=PropertyChanged}">
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
FilteredList.Value.Lot.TypeImpression is a string.
If I've well understood, all the possible string must be in the ItemSource otherwise they could'nt be displayed. But I need to find a way to prevent user to select some of them.
Thanks for your help.
I don't know of a way to make individual items non-selectable in a combo box.
But you could always show a combo box without your not-allowed letters (i.e. remove them from AvailableTypeImpression), and instead show just a simple TextBlock in your cell in case one of these letters is read from the DB.
Change your cell template to something like this:
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Grid>
<ComboBox Visbility="{Binding IsValueEditable}" Height="23" Style="{StaticResource AnfComboBoxStyle}" ItemsSource="{Binding DataContext.AvailableTypeImpression, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}" SelectedItem="{Binding Value.Lot.TypeImpression, UpdateSourceTrigger=PropertyChanged}" />
<TextBlock Visbility="{Binding NotIsValueEditable}" Height="23" Text="{Binding Value.Lot.TypeImpression}" />
</Grid>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
Then implement IsValueEditable, NotIsValueEditable properties in your ViewModel such that only one of the controls is shown.
Alternatively, if you also want to be able to modify existing entries of M, p, P, R, you could use a DataGridTemplateColumn.CellEditingTemplate:
Make the CellEditingTemplate show the ComboBox (without M, p, P, R options) while the regular CellTemplate only contains a TextBlock.
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Height="23" Text="{Binding Value.Lot.TypeImpression}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox Height="23" Style="{StaticResource AnfComboBoxStyle}" ItemsSource="{Binding DataContext.AvailableTypeImpression, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}" SelectedItem="{Binding Value.Lot.TypeImpression, UpdateSourceTrigger=PropertyChanged}" />
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
The solution from #dheller was good but not working in my case because the user is not able to give to "Value.Lot.TypeImpression" a new Value M ,p, P or R, but he's able to edit "Value.Lot.TypeImpression" even if it equals to M ,p, P or R and set S, D, T, or X.
So I've found another way :
In my ViewModel I've defined a new class :
public class TypeImpressionAvailable
{
public string Name { get; set; }
public bool IsAvailable { get; set; }
}
And my list to give to my combobox as ItemSource :
public List<TypeImpressionAvailable> AvailableTypeImpression { get; } = new List<TypeImpressionAvailable>() {
new TypeImpressionAvailable(){ Name="N", IsAvailable=true },
new TypeImpressionAvailable(){ Name="S", IsAvailable=true },
new TypeImpressionAvailable(){ Name="D", IsAvailable=true },
new TypeImpressionAvailable(){ Name="T", IsAvailable=true },
new TypeImpressionAvailable(){ Name="X", IsAvailable=true },
new TypeImpressionAvailable(){ Name="M", IsAvailable=false },
new TypeImpressionAvailable(){ Name="p", IsAvailable=false },
new TypeImpressionAvailable(){ Name="P", IsAvailable=false },
new TypeImpressionAvailable(){ Name="R", IsAvailable=false }
};
And in my View :
<DataGridTemplateColumn Header=".i." HeaderStyle="{StaticResource CenteredColumnHeaderStyle}" Width="45" IsReadOnly="False">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox Height="23" SelectedValuePath="Name" DisplayMemberPath="Name"
SelectedValue="{Binding Value.Lot.TypeImpression, UpdateSourceTrigger=PropertyChanged}"
>
<ComboBox.Style>
<Style TargetType="{x:Type ComboBox}" BasedOn="{StaticResource AnfComboBoxStyle}">
<Setter Property="ItemsSource" Value="{Binding DataContext.AvailableTypeImpression, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}"/>
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style TargetType="ComboBoxItem" BasedOn="{StaticResource {x:Type ComboBoxItem}}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsAvailable}" Value="False">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</Setter.Value>
</Setter>
</Style>
</ComboBox.Style>
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
And it works fine :)

DataTrigger not firing when property changed in DataGrid SelectedItem

I'm trying to have a datatrigger fire when I update a property on my DataGrid for the SelectedItem. Can someone show me what I need to change to get it to work?
When a user selects an item in the grid, its Connected property gets set to true. My label in the DataGrid is supposed to change from red to green. It stays red.
I know the style works because if I start out with the property Connected set to true, they all come out green. It just does not seem to fire when the user selects an item in the DataGrid.
// Style set in Resources of my control
<Style x:Key="ConnectedStyle" TargetType="{x:Type Label}"
BasedOn="{StaticResource FontAwesome}">
<Setter Property="Foreground" Value="Red" /> // I added this last
minute thinking it might need to be initialized but still nothing.
<Style.Triggers>
<DataTrigger Binding="{Binding Connected}" Value="True">
<Setter Property="Foreground" Value="Green" />
</DataTrigger>
<DataTrigger Binding="{Binding Connected}" Value="False">
<Setter Property="Foreground" Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>
<DataGrid Grid.Row="1" Grid.Column="1"
ItemsSource="{Binding AvailablePorts}"
SelectedItem="{Binding SelectedPort}"
HorizontalAlignment="Stretch"
SelectionMode="Single"
Style="{StaticResource PlainGrid}"
AutoGenerateColumns="False" ColumnHeaderHeight="30">
<DataGrid.Columns>
<DataGridTemplateColumn Header=" Status" Width="55">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Label Style="{StaticResource ConnectedStyle}"
Content="" FontSize="12" Margin="5,0,0,0"
Padding="0" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header=" Port" Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Port}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
View Model
public class EMSViewModel : ViewModelDetailBase<EMSViewModel, EMSModel>
{
public ObservableCollection<AvailablePortsModel> AvailablePorts
{
get
{
return this.availablePorts;
}
private set
{
this.availablePorts = value;
this.NotifyPropertyChanged(m => m.AvailablePorts);
}
}
public AvailablePortsModel SelectedPort
{
get
{
return this.selectedPort;
}
set
{
this.selectedPort = value;
this.NotifyPropertyChanged(m => m.SelectedPort);
this.ConnectToPort();
}
}
private void ConnectToPort()
{
// if the code (removed) evaluates to true, set the connected property to true.
this.SelectedPort.Connected = true;
this.NotifyPropertyChanged(m => m.AvailablePorts);
}
}
Model
namespace FastV.Models
{
using SimpleMvvmToolkit;
public class AvailablePortsModel : ModelBase<AvailablePortsModel>
{
private bool connected;
private string port;
public bool Connected
{
get
{
return this.connected;
}
set
{
this.connected = value;
this.NotifyPropertyChanged(m => m.Connected);
}
}
public string Port
{
get
{
return this.port;
}
set
{
this.port = value;
this.NotifyPropertyChanged(m => m.Port);
}
}
}
}

DataGrid DataGridTemplateColumn ComboBox

I'm having trouble with my ComboBoxes in a DataGrid, let me explain with a few pictures.
This is the starting point.
Now if I want to add a new row I click the last row and hit Enter.
A new row is added and iv selected type table here and given it a name MY_TABLE, then I hit enter to add another row.
The result is this, the combobox for the previous added row's type selection has gone back to None. NOTE: that the checkboxes were previously grayed out as type None cant have any privileges, but table can have CRUD so when I selected type table they became enabled.
Here is the ViewModel (VM) for each row:
public class RoleHasPrivilegeOnObjectEntityViewModel : EntityViewModelBase<RoleHasPrivilegeOnObjectEntityViewModel, RoleHasPrivilegesOnObject>, IRoleHasPrivilegeOnObjectListItemViewModel
{
private readonly RoleHasPrivilegesOnObject _roleHasPrivilegesOnObject;
private ObservableCollection<ObjectTypeEntityViewModel> _availableObjectTypes;
private readonly ObjectTypeEntityViewModel _objectTypeEntityViewModel;
private IRoleEntityViewModel _role;
private IObjectEntityViewModel _object;
public RoleHasPrivilegeOnObjectEntityViewModel(RoleHasPrivilegesOnObject roleHasPrivilegesOnObject, IEnumerable<OBJECT_TYPE> availableObjectTypes)
{
_roleHasPrivilegesOnObject = roleHasPrivilegesOnObject;
AvailableObjectTypes = new ObservableCollection<ObjectTypeEntityViewModel>(availableObjectTypes.Select(ot => new ObjectTypeEntityViewModel(ot)));
_role = new RoleEntityViewModel(_roleHasPrivilegesOnObject.Role);
_object = new ObjectEntityViewModel(_roleHasPrivilegesOnObject.Object);
_objectTypeEntityViewModel = new ObjectTypeEntityViewModel(_roleHasPrivilegesOnObject.Object.OBJECT_TYPE);
}
public RoleHasPrivilegeOnObjectEntityViewModel(XROLE role, CONTAINER schema, OBJECT_TYPE currentObjectType, IEnumerable<OBJECT_TYPE> availableObjectTypes)
{
var objectTypes = availableObjectTypes as IList<OBJECT_TYPE> ?? availableObjectTypes.ToList();
_roleHasPrivilegesOnObject = new RoleHasPrivilegesOnObject(role,
new XOBJECT { CONTAINER = schema, OBJECT_TYPE = currentObjectType },
new List<OBJECT_HAS_PRIVILEGE>(),
objectTypes.SelectMany(aot => aot.PRIVILEGE));
AvailableObjectTypes = new ObservableCollection<ObjectTypeEntityViewModel>(objectTypes.Select(ot => new ObjectTypeEntityViewModel(ot)));
_role = new RoleEntityViewModel(_roleHasPrivilegesOnObject.Role);
_object = new ObjectEntityViewModel(_roleHasPrivilegesOnObject.Object);
_objectTypeEntityViewModel = new ObjectTypeEntityViewModel(_roleHasPrivilegesOnObject.Object.OBJECT_TYPE);
}
public override EntityType EntityType
{
get { return SelectedObjectType.EntityType; }
}
public ObjectTypeEntityViewModel SelectedObjectType
{
get { return _objectTypeEntityViewModel; }
set
{
_roleHasPrivilegesOnObject.Object.OBJECT_TYPE = value.OriginalEntity;
OnPropertyChanged();
OnPropertyChanged("CanHaveSelect");
...
}
}
public ObservableCollection<ObjectTypeEntityViewModel> AvailableObjectTypes
{
get { return _availableObjectTypes; }
set
{
_availableObjectTypes = value;
OnPropertyChanged();
}
}
public string ToolTip
{
get { return _roleHasPrivilegesOnObject.ToolTip; }
}
public bool HasSelect
{
get { return _roleHasPrivilegesOnObject.HasSelect; }
set
{
_roleHasPrivilegesOnObject.HasSelect = value;
OnPropertyChanged();
}
}
public bool CanHaveSelect
{
get
{
var canHaveSelect = _roleHasPrivilegesOnObject.CanHaveSelect;
if(!canHaveSelect && HasSelect) HasSelect = false;
return canHaveSelect;
}
}
...
public override string NAME
{
get { return _roleHasPrivilegesOnObject.NAME; }
set
{
_roleHasPrivilegesOnObject.NAME = value;
OnPropertyChanged();
OnPropertyChanged("Text");
}
}
}
And here is my View for the DataGrid
<UserControl ...
d:DataContext="{d:DesignInstance impl:PrivilegeDetailsViewModel}">
<UserControl.Resources>
<Style x:Key="DataGridContentCellCentering" TargetType="{x:Type DataGridCell}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Grid Background="{TemplateBinding Background}">
<ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="CanHaveSelectStyle" TargetType="CheckBox">
<Style.Triggers>
<DataTrigger Binding="{Binding CanHaveSelect, UpdateSourceTrigger=PropertyChanged}" Value="True">
<Setter Property="IsEnabled" Value="True"/>
</DataTrigger>
<DataTrigger Binding="{Binding CanHaveSelect, UpdateSourceTrigger=PropertyChanged}" Value="False">
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
</Style.Triggers>
</Style>
...
</UserControl.Resources>
<DataGrid x:Name="PrivilegeDataGrid"
ItemsSource="{Binding RolesHasPrivilegesOnObjects}"
AutoGenerateColumns="False"
CanUserReorderColumns="False"
CanUserResizeColumns="True"
CanUserResizeRows="False"
CanUserSortColumns="True"
CanUserAddRows="True"
IsTextSearchEnabled="True"
BorderThickness="0">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Type" CanUserSort="True" MinWidth="120">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate DataType="{x:Type impl2:RoleHasPrivilegeOnObjectEntityViewModel}">
<ComboBox ItemsSource="{Binding AvailableObjectTypes}"
SelectedItem="{Binding SelectedObjectType}"
SelectedValue="{Binding SelectedObjectType.ID}"
SelectedValuePath="ID">
<ComboBox.ItemTemplate>
<DataTemplate DataType="{x:Type impl2:ObjectTypeEntityViewModel}">
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Icon}" ToolTip="{Binding ToolTip}" Margin="0,0,3,0" Width="17" Height="17"/>
<TextBlock Text="{Binding ToolTip}"/>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Width="*" Header="Name" Binding="{Binding NAME}">
<DataGridTextColumn.EditingElementStyle>
<Style TargetType="TextBox">
<Setter Property="extensions:TextBoxUpperCaseBehavior.IsEnabled" Value="True"/>
</Style>
</DataGridTextColumn.EditingElementStyle>
</DataGridTextColumn>
<DataGridCheckBoxColumn Header="Select"
Binding="{Binding HasSelect, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
CellStyle="{StaticResource DataGridContentCellCentering}"
ElementStyle="{StaticResource CanHaveSelectStyle}"
EditingElementStyle="{StaticResource CanHaveSelectStyle}" />
...
</DataGrid.Columns>
</DataGrid>
</UserControl>
I have tried all these variants for the ComboBox ItemsSource and SelectedItem
<ComboBox ItemsSource="{Binding AvailableObjectTypes}"
SelectedItem="{Binding SelectedObjectType}"
SelectedValue="{Binding SelectedObjectType.ID}"
SelectedValuePath="ID">
<ComboBox ItemsSource="{Binding AvailableObjectTypes}"
SelectedValue="{Binding SelectedObjectType.ID}"
SelectedValuePath="ID">
<ComboBox ItemsSource="{Binding AvailableObjectTypes}"
SelectedItem="{Binding SelectedObjectType}"
SelectedValuePath="ID">
<ComboBox ItemsSource="{Binding AvailableObjectTypes}"
SelectedItem="{Binding SelectedObjectType}">
What do I have to do to make the ComboBox behave as expected?
It seems that a simple UpdateSourceTrigger attribute was missing on the SelectedObjectType binding in the xaml for the ComboBox, like this
<ComboBox ItemsSource="{Binding AvailableObjectTypes}"
SelectedItem="{Binding SelectedObjectType, UpdateSourceTrigger=PropertyChanged}"
SelectedValue="{Binding SelectedObjectType.ID}"
SelectedValuePath="ID">

wpf datagrid automatically expand first group

I have a datagrid with the itemsource bound to a ListCollectionView with one group.
When i fill the collection, i want the first group autmatically viewed as expanded, how to code that in wpf (codebehind or mvvm)?
<DataGrid
ItemsSource="{Binding ResultColl}"
SelectedItem="{Binding Path=SelectedResultItem, Mode=TwoWay}"
SelectionMode="Single" IsReadOnly="True" >
<DataGrid.GroupStyle>
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander>
<Expander.Header>
<StackPanel>
<TextBox Text="{Binding Items[0].ID}" />
</StackPanel>
</Expander.Header>
<ItemsPresenter />
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</DataGrid.GroupStyle>
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Path=ID}"/>
<DataGridTextColumn Binding="{Binding Path=Typ}"/>
<DataGridTextColumn Binding="{Binding Path=Info}"/>
<DataGridTextColumn Binding="{Binding Path=orderDate, StringFormat={}{0:dd-MM-yyyy}}"/>
</DataGrid.Columns>
</DataGrid>
In the mvvm controller:
ListCollectionView tmp = new ListCollectionView(myList);
tmp.GroupDescriptions.Add(new PropertyGroupDescription("ID"));
ResultColl = tmp;
...
ListCollectionView _resultColl;
public ListCollectionView ResultColl
{
get { return _resultColl; }
set { _resultColl = value;
RaisePropertyChanged("ResultColl");
if (value != null && _resultColl.Count > 0)
SelectedResultItem = _resultColl.GetItemAt(0) as ItemResult;
}
}
When executing the code, the datagrid is filled the 1st item is selected but group is collapsed.
Add IsExpanded property to your class and add binding to Expander:
<Expander IsExpanded="{Binding Items[0].IsExpanded}">
Set IsExpanded for first to true
you can try add another bool property to your View Model defaulted to true but switching to false when first time used. And bind IsExpanded property of Expander to this with OneTime mode.
public bool IsExpanded
{
get
{
if (_isExpanded)
{
_isExpanded = false;
return true;
}
return false;
}
}
Xaml would be like that:
<Expander IsExpanded="{Binding DataContext.IsExpanded, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}, Mode=OneTime}">

How to bind ObservableCollection in DataGridComboBoxColumn in DataGrid?

I have already given ListCollectionView as "ListCollectionView1" to Grid and inGrid I have used DataGrid. "ListCollectionView1" contains both observable collection. "ObservableCollection1" DataGrid in and another observable collection as "ObservableCollection2" which is in "ObservableCollection1" observable collection as Itemsource to DataGridComboBoxColumn .
And as SelectedValueBinding I'm using Property as "a" from "ObservableCollection1"
but I'm not getting the values in DataGridComboBoxColumn
<Grid DockPanel.Dock="Bottom" DataContext="{Binding ListCollectionView1>
<DataGrid
ColumnWidth="130"
CanUserAddRows="True"
AutoGenerateColumns="False"
ItemContainerStyle="{StaticResource DataGridRowContentStyle}"
ItemsSource="{Binding ObservableCollection1 }"
CanUserDeleteRows="False">
<DataGridComboBoxColumn Header="Labour" ItemsSource="{Binding Path=ObservableCollection2 , RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" SelectedValueBinding="{Binding Id}" SelectedValuePath="Id" DisplayMemberPath="Id" HeaderStyle="{StaticResource DataGridHeaderStyle}"/>
</DataGrid>
</Grid>
in my viewModel observable collections and listcollectionview are
private ListCollectionView _ListCollectionView1;
public ListCollectionView ListCollectionView1
{
get { return _ListCollectionView1; }
set
{
this._ListCollectionView1= value;
OnPropertyChanged("ListCollectionView1");
}
}
public ObservableCollection<Model_ObservableCollection1> ModelObservableCollection1
{
get { return new ObservableCollection<Model_ObservableCollection1>(ViewModel.AllDataCollactions.AllTransactionsDetails.Where(s => s.TransactionsID.Equals(TransactionsID))); }
}
public ObservableCollection<Model_ObservableCollection2> Model_ObservableCollection1
{
get { return new ObservableCollection<Model_ObservableCollection1>(ViewModel.AllDataCollactions.AllTransactionsDetails.Where(s => s.TransactionsID.Equals(TransactionsID) && s.IsJama)); }
}
Try this.
<DataGrid x:Name="testGrid" AutoGenerateColumns="True" ItemsSource="{Binding ObservableCollection}" >
<DataGrid.Columns>
<DataGridComboBoxColumn Header="Labour" DisplayMemberPath="test">
<DataGridComboBoxColumn.ElementStyle>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="ItemsSource" Value="{Binding Path=DataContext.ObservableCollection2 , RelativeSource={RelativeSource AncestorType={x:Type Window}}}" />
</Style>
</DataGridComboBoxColumn.ElementStyle>
<DataGridComboBoxColumn.EditingElementStyle>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="ItemsSource" Value="{Binding Path=DataContext.ObservableCollection2, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" />
</Style>
</DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>
</DataGrid.Columns>
</DataGrid>
Add the DataContext in your style binding instead of just the property name. You are just setting the ItemsSource of the ColumnBoxHeader which doesn't make sense. It doesn't know how to populate the ComboBox where it is in the children of the control.

Resources