简体   繁体   中英

Binding for ComboBox Header in DataGrid

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).

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}}}"

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; }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM