Reputation: 634
I have a DataGrid in a WPF MVVM pattern application, and I am trying to use a combo box in the header to filter the grid. I can do this when all of the code is in the Window class (not MVVM) but for my own sake I am trying to bind it to the VM to get the same results. Here's the XAML:
<DataGridTextColumn x:Name="transNameColumn" Binding="{Binding TransName}" Width="325">
<DataGridTextColumn.Header>
<ComboBox ItemsSource="{Binding oTran}" DisplayMemberPath="TransName" SelectedValuePath="UID"
HorizontalAlignment="Left" Width="315">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding Transmittal_ComboSelect}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ComboBox>
</DataGridTextColumn.Header>
The DataGrid in which this resides looks like this (just the top where the binding is):
<DataGridTextColumn x:Name="transNameColumn" Binding="{Binding TransName}" Width="325">
<DataGridTextColumn.Header>
<ComboBox ItemsSource="{Binding oTran}" DisplayMemberPath="TransName" SelectedValuePath="UID"
HorizontalAlignment="Left" Width="315">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding Transmittal_ComboSelect}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ComboBox>
</DataGridTextColumn.Header>
and the top level grid is bound thusly:
<Grid DataContext="{Binding}">
I am thinking that because the combo box is inside the datagrid the binding gets messed up. When I have the combo box on its own, with the same XAML it works fine. But when inserted as the header it does not populate (and I think the event binding will also not work, but can't verify as it does not populate so there's no way to make a selection).
Upvotes: 1
Views: 3723
Reputation: 5366
Adding to kelly suggestion. Refer the complete code for adding combobox column.
<Grid>
<DataGrid AutoGenerateColumns="False" Name="dgr" ItemsSource="{Binding GridItems}" >
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Name}" >
<DataGridTextColumn.Header>
<StackPanel Orientation="Horizontal">
<TextBlock Text="combo" Grid.Row="0"/>
<ComboBox Grid.Row="1" Width="70" HorizontalAlignment="Center" Name="cboBhp"
ItemsSource="{Binding Path=DataContext.ComboItems,
RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
SelectedValue="{Binding Path=DataContext.ComboValue, RelativeSource={RelativeSource AncestorType={x:Type Window}},
Mode=TwoWay}">
</ComboBox>
</StackPanel>
</DataGridTextColumn.Header>
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
this.DataContext = new MainViewModel();
}
}
public class GridSample
{
public string Name { get; set; }
}
public class MainViewModel:INotifyPropertyChanged
{
private string comboValue;
public string ComboValue
{
get { return comboValue; }
set
{
if (comboValue != value)
{
comboValue = value;
NotifyPropertyChanged("ComboValue");
}
}
}
public MainViewModel()
{
ComboItems = new ObservableCollection<string>();
ComboItems.Add("pascal");
ComboItems.Add("Braye");
ComboValue = "pascal";
GridItems = new ObservableCollection<GridSample>() {
new GridSample() { Name = "Jim"} ,new GridSample() { Name = "Adam"} };
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string str)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(str));
}
}
public ObservableCollection<GridSample> GridItems { get; set; }
public ObservableCollection<string> ComboItems { get; set; }
}
Upvotes: 1
Reputation: 7183
You need to use RelativeSource in your binding. It will end up looking something like this:
"{Binding DataContext.oTran, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}"
Upvotes: 2