Selected item not displayed in the DataGridComboBo

2019-09-16 01:23发布

I have a DataGrid with two DataGridComboBoxColumns set in the XAML (copied from here):

<DataGrid x:Name="joinGrid" AutoGenerateColumns="False" CanUserAddRows="True">
                <DataGrid.Columns>
                    <DataGridComboBoxColumn>
                        <DataGridComboBoxColumn.ElementStyle>
                            <Style TargetType="ComboBox">
                                <Setter Property="IsDropDownOpen" Value="True" />
                                <Setter Property="ItemsSource" Value="{Binding Path=TableAColumns}" />
                                <Setter Property="ItemTemplate">
                                    <Setter.Value>
                                        <DataTemplate>
                                            <TextBlock Text="{Binding}"></TextBlock>
                                        </DataTemplate>
                                    </Setter.Value>
                                </Setter>
                            </Style>
                        </DataGridComboBoxColumn.ElementStyle>
                        <DataGridComboBoxColumn.EditingElementStyle >
                            <Style TargetType="ComboBox">
                                <Setter Property="ItemsSource" Value="{Binding Path=TableAColumns}" />
                                <Setter Property="IsDropDownOpen" Value="True" />
                                <Setter Property="ItemTemplate">
                                    <Setter.Value>
                                        <DataTemplate>
                                            <TextBlock Text="{Binding}"></TextBlock>
                                        </DataTemplate>
                                    </Setter.Value>
                                </Setter>
                            </Style>
                        </DataGridComboBoxColumn.EditingElementStyle>
                    </DataGridComboBoxColumn>

                    <DataGridComboBoxColumn>
                        <DataGridComboBoxColumn.ElementStyle>
                            <Style TargetType="ComboBox">
                                <Setter Property="IsDropDownOpen" Value="True" />
                                <Setter Property="ItemsSource" Value="{Binding Path=TableBColumns}" />
                                <Setter Property="ItemTemplate">
                                    <Setter.Value>
                                        <DataTemplate>
                                            <TextBlock Text="{Binding}"></TextBlock>
                                        </DataTemplate>
                                    </Setter.Value>
                                </Setter>
                            </Style>
                        </DataGridComboBoxColumn.ElementStyle>
                        <DataGridComboBoxColumn.EditingElementStyle>
                            <Style TargetType="ComboBox">
                                <Setter Property="ItemsSource" Value="{Binding Path=TableBColumns}" />
                                <Setter Property="IsDropDownOpen" Value="True" />
                                <Setter Property="ItemTemplate">
                                    <Setter.Value>
                                        <DataTemplate>
                                            <TextBlock Text="{Binding}"></TextBlock>
                                        </DataTemplate>
                                    </Setter.Value>
                                </Setter>
                            </Style>
                        </DataGridComboBoxColumn.EditingElementStyle>
                    </DataGridComboBoxColumn>
                </DataGrid.Columns>
            </DataGrid>

with few exceptions because honestly i do not understand what should go in the missing porperties. I am trying to bind the columns to lists of strings contained in an entity class:

class JoinBlockDTO
{
    public List<string> TableAColumns { get; set; }
    public List<string> TableBColumns { get; set; }
}

In my code behind, i set the grid's ItemsSource:

DataGrid dg = (DataGrid)GetTemplateChild("joinGrid");

List<JoinBlockDTO> l = new List<JoinBlockDTO>();
List<string> colAList = (from DataRowView row in sourceA
                         select row.Row.Field<string>(0)).ToList();
List<string> colBList = (from DataRowView row in sourceB
                         select row.Row.Field<string>(0)).ToList();

((DataGridComboBoxColumn)dg.Columns[0]).ItemsSource = colAList; //doesn't work without this
((DataGridComboBoxColumn)dg.Columns[1]).ItemsSource = colBList; //doesn't work without this
l.Add (new JoinBlockDTO(){TableAColumns = colAList, TableBColumns = colBList});
dg.ItemsSource = l;

All this, initially, renders a 2 x 2 grid with all blank cells. I click twice to see a drop-down with the list of strings bound properly. However, when i select a value from the drop-down and shift the focus outside, the cell is left blank. Can someone point out what should be added to the XAML or modified? Is there a simpler way to do this binding? I have read numerous posts about this combo-box column binding but could not understand what was going on. (Using VS2010)

3条回答
叛逆
2楼-- · 2019-09-16 01:50

Perhaps your VM doesn't implement INotifyPropertyChanged interface.

Here is an example:

<Window x:Class="wpfProj.MainWindow"
        ...
        d:DataContext="{d:DesignInstance wpfProj:MainViewModel}">

    <Grid >
        <Grid.Resources>
            <wpfProj:BindingProxy x:Key="proxy" Data="{Binding}"/>
        </Grid.Resources>
        <DataGrid AutoGenerateColumns="False" ItemsSource="{Binding Path=Persons}">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Name" Binding="{Binding Path=Name}" Width="*"/>
                <DataGridComboBoxColumn Header="Sex" Width="*" ItemsSource="{Binding Source={StaticResource proxy}, Path=Data.SexList}"
                                        SelectedItemBinding="{Binding Path=Sex}"/>
                <DataGridComboBoxColumn Header="Sex" Width="*" ItemsSource="{Binding Source={x:Static wpfProj:DataCollection.Instance}, Path=SexList}"
                                        SelectedItemBinding="{Binding Path=Sex}"/>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

I placed two "Sex" columns just to show two ways to bind to source. In first case, SexList is a part of ViewModel (DataContext), that's why I used proxy. In the second case it's binded to the singleton's property.

Sex property:

    public string Sex
    {
        get { return _sex; }
        set
        {
            _sex = value;
            OnPropertyChanged("Sex");
        }
    }

And the proxy class (I've found it in the Internet, don't remember the link to the author's page)

public class BindingProxy : Freezable
{
    #region Overrides of Freezable

    protected override Freezable CreateInstanceCore()
    {
        return new BindingProxy();
    }

    #endregion

    public object Data
    {
        get { return GetValue(DataProperty); }
        set { SetValue(DataProperty, value); }
    }

    public static readonly DependencyProperty DataProperty =
        DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null));
}

Hope it helps. Here is the sample I've uploaded.

查看更多
3楼-- · 2019-09-16 02:00

this will help u

use "ObservableCollection"List to auto INotifyPropertyChanged

 <DataGrid x:Name="myDataGridTeacher" 
                  ItemsSource="{Binding ObservableCollectionList}" >

 <DataGridTemplateColumn Width="*" Header="MyHeader"  >
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate >

                            <TextBlock Text="{Binding Material_Name.Name}" 
                                  />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>

                    <DataGridTemplateColumn.CellEditingTemplate>
                        <DataTemplate>
                            <ComboBox  
                                       ItemsSource="{Binding Material_Name}" 
                                       DisplayMemberPath="Name"

                                />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellEditingTemplate>

                </DataGridTemplateColumn>

 </DataGrid>

ItemsSource="{Binding Material_Name}" is List in "ObservableCollectionList"

<TextBlock Text="{Binding Material_Name.Name}" 
                                      />
查看更多
4楼-- · 2019-09-16 02:02

Right so, I figured it out.

Use SelectedValueBinding={Binding object} and SelectedValuePath="" That fixed it for me.

WPF: Databinding with DataGridComboBoxColumn

查看更多
登录 后发表回答