如何在数据网格内绑定ComboBox? [英] How to Bind ComboBox inside a Datagrid?

查看:56
本文介绍了如何在数据网格内绑定ComboBox?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个称为组的表,如下所示:



在上面的图片中,我认为您可能已经理解主键和外键存在于同一张表中。我认为这就是开发人员所谓的循环引用。



在MainWindow.xaml中,我有一个DataGrid,其中包含三列,即组名,父名,描述。 xaml看起来像:

 < Window .......> 

< Window.DataContext>
< self:MainWindowViewModel />
< /Window.DataContext>

< DataGrid ItemsSource = {Binding Groups} TabIndex = 1>

< DataGrid.Columns>

< DataGridTemplateColumn Header = Group Name Width = 2 *>
< DataGridTemplateColumn.CellTemplate>
< DataTemplate>
< TextBlock Text = {Binding GroupName} />
< / DataTemplate>
< /DataGridTemplateColumn.CellTemplate>
< DataGridTemplateColumn.CellEditingTemplate>
< DataTemplate>
< TextBox Text = {Binding GroupName} />
< / DataTemplate>
< /DataGridTemplateColumn.CellEditingTemplate>
< / DataGridTemplateColumn>

< DataGridTemplateColumn Header = Parent Width = 2 *>
< DataGridTemplateColumn.CellTemplate>
< DataTemplate>
< TextBlock Text = {Binding ParentID} />
< / DataTemplate>
< /DataGridTemplateColumn.CellTemplate>
< DataGridTemplateColumn.CellEditingTemplate>
< DataTemplate>
< ComboBox ItemsSource = {Binding DataContext.GroupsCollection,RelativeSource = {RelativeSource Mode = FindAncestor,AncestorType = {x:Type Window}}}
SelectedValue = {Binding ParentID}
DisplayMemberPath = GroupName />
< / DataTemplate>
< /DataGridTemplateColumn.CellEditingTemplate>
< / DataGridTemplateColumn>

< DataGridTemplateColumn Header = Description Width = 2 *>
< DataGridTemplateColumn.CellTemplate>
< DataTemplate>
< TextBlock Text = {绑定描述} />
< / DataTemplate>
< /DataGridTemplateColumn.CellTemplate>
< DataGridTemplateColumn.CellEditingTemplate>
< DataTemplate>
< TextBox文字= {绑定描述} />
< / DataTemplate>
< /DataGridTemplateColumn.CellEditingTemplate>
< / DataGridTemplateColumn>

< / power:PowerDataGrid.Columns>

< / power:PowerDataGrid>

< / Window>

现在我有一个名为MainWindowViewModel的ViewModel

 公共类MainWindowViewModel:INotifyPropertyChanged 
{
public MainWindowViewModel()
{
SampleDBContext sampleDBContext = new SampleDBContext();
Groups = new ObservableCollection< Group>();
GroupsCollection = new ObservableCollection< Group>(从sampleDBContext.g中的g中选择g);
}

私人ObservableCollection< Group> _groups;
public ObservableCollection< Group>组
{
获得
{
return _groups;
}
set
{
_groups = value;
OnPropertyChanged( Groups);
}
}

私人ObservableCollection< Group> _groupsCollection;
public ObservableCollection< Group> GroupsCollection
{
get
{
return _groupsCollection;
}
set
{
_groupsCollection = value;
OnPropertyChanged( GroupsCollection);
}
}

#region INotifyPropertyChanged

公共事件PropertyChangedEventHandler PropertyChanged;

受保护的无效OnPropertyChanged(字符串propertryName)
{
if(PropertyChanged!= null)
{
PropertyChanged(this,new PropertyChangedEventArgs(propertryName)) ;
}
}

#endregion
}

问题:

 输出:



如上图所示,当我在父列中选择一个组后按TAB或Enter时,下一个单元格被聚焦,但是父列下的单元格有一个红色的轮廓,表示一些错误。而且单元格不会离开编辑模式。我在输出窗口中也遇到很多绑定错误。因此,我知道我的绑定不正确。有人可以帮我将 Combobox 绑定到 datagrid 内吗?



更新:



如果我按如下方式使用SelectedValuePath:

 <组合框ItemsSource = {Binding DataContext.GroupsCollection,RelativeSource = {RelativeSource Mode = FindAncestor,AncestorType = {x:Type Window}}} 
SelectedValue = {Binding ParentID} SelectedValuePath = {Binding GroupID}
DisplayMemberPath = GroupName />

然后错误消失了,单元格也离开了编辑模式。但是,然后TextBlock(它是celltemplate)始终保持为空。

解决方案

解决了它。我不应该在SelectedValuePath中使用绑定。因此,现在我的代码应类似于:

 < ComboBox ItemsSource = {Binding DataContext.GroupsCollection,RelativeSource = {RelativeSource Mode = FindAncestor,AncestorType = {x:Type窗口}}} 
SelectedValue = {Binding ParentID} SelectedValuePath = GroupID
DisplayMemberPath = GroupName />

现在的问题是:



我明白了由于我对CellTemplate的绑定,在完成编辑模式后,ComboBox的SelectedValue的ID(但我想用名称代替ID):

 < DataGridTemplateColumn Header = Parent Width = 2 *> 
< DataGridTemplateColumn.CellTemplate>
< DataTemplate>
< TextBlock Text = {Binding ParentID} />
< / DataTemplate>
< /DataGridTemplateColumn.CellTemplate>
< DataGridTemplateColumn.CellEditingTemplate>
< DataTemplate>
< ComboBox ItemsSource = {Binding DataContext.GroupsCollection,RelativeSource = {RelativeSource Mode = FindAncestor,AncestorType = {x:Type Window}}}}
SelectedValue = {Binding ParentID} SelectedValuePath = GroupID
DisplayMemberPath = GroupName />
< / DataTemplate>
< /DataGridTemplateColumn.CellEditingTemplate>
< / DataGridTemplateColumn>

所以我创建了一个转换器,如下所示:

 公共类GroupIDToGroupName:IValueConverter 
{
公共对象Convert(对象值,类型targetType,对象参数,System.Globalization.CultureInfo文化)
{
if(value!= null)
{
SampleDBContext sampleDBContext = new SampleDBContext();
返回(从sampleDBContext.Groups
中的g返回,其中g.GroupID ==(int)value
选择g.GroupName).FirstOrDefault();
}
其他
{
返回;
}
}

公共对象ConvertBack(对象值,类型targetType,对象参数,System.Globalization.CultureInfo文化)
{
SampleDBContext sampleDBContext =新的SampleDBContext();
返回(从sampleDBContext.Groups
中的g返回,其中g.GroupName ==(字符串)值
选择g.GroupID).FirstOrDefault();
}
}

我在App.xaml中将该转换器声明为:

 < self:GroupIDToGroupName x:Key = GroupIDToGroupNameConveerter /> 

现在,我的Cell模板看起来像:

 < TextBlock Text = {Binding ParentID,Converter = {StaticResource GroupIDToGroupNameConveerter}} /> 

我不知道我是否以正确的方式解决了我的问题。但是它的工作!!!!!!!



如果有人有个好主意,请分享...........


I have a table called groups as shown below :

After looking at the image above I think you might have understood that primary key and foreign key exist in the same table. I think this is what developers call cyclic reference.

In MainWindow.xaml I have a DataGrid which contains three columns namely Group Name, Parent Name, Description. The xaml looks like :

<Window .......>

    <Window.DataContext>
        <self:MainWindowViewModel />
    </Window.DataContext>

    <DataGrid ItemsSource="{Binding Groups}" TabIndex="1">

        <DataGrid.Columns>

            <DataGridTemplateColumn Header="Group Name" Width="2*">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding GroupName}"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
                <DataGridTemplateColumn.CellEditingTemplate>
                    <DataTemplate>
                        <TextBox Text="{Binding GroupName}" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellEditingTemplate>
            </DataGridTemplateColumn>

            <DataGridTemplateColumn Header="Parent" Width="2*">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding ParentID}" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
                <DataGridTemplateColumn.CellEditingTemplate>
                    <DataTemplate>
                        <ComboBox ItemsSource="{Binding DataContext.GroupsCollection, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"
                                  SelectedValue="{Binding ParentID}"
                                  DisplayMemberPath="GroupName"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellEditingTemplate>
            </DataGridTemplateColumn>

            <DataGridTemplateColumn Header="Description" Width="2*">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Description}"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
                <DataGridTemplateColumn.CellEditingTemplate>
                    <DataTemplate>
                        <TextBox Text="{Binding Description}"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellEditingTemplate>
            </DataGridTemplateColumn>

        </power:PowerDataGrid.Columns>

    </power:PowerDataGrid>

</Window>

Now I have a ViewModel called MainWindowViewModel

public class MainWindowViewModel : INotifyPropertyChanged
{
    public MainWindowViewModel()
    {
        SampleDBContext sampleDBContext = new SampleDBContext();
        Groups = new ObservableCollection<Group>();
        GroupsCollection = new ObservableCollection<Group>(from g in sampleDBContext.Groups select g);
    }

    private ObservableCollection<Group> _groups;
    public ObservableCollection<Group> Groups
    {
        get
        {
            return _groups;
        }
        set
        {
            _groups = value;
            OnPropertyChanged("Groups");
        }
    }

    private ObservableCollection<Group> _groupsCollection;
    public ObservableCollection<Group> GroupsCollection
    {
        get
        {
            return _groupsCollection;
        }
        set
        {
            _groupsCollection = value;
            OnPropertyChanged("GroupsCollection");
        }
    }

    #region INotifyPropertyChanged

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertryName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertryName));
        }
    }

    #endregion
}

Problems :

Output :

As you can see in the above image when I press TAB or Enter after selecting a group in Parent Column the next cell is focused but cell Under Parent Column has a red Outline indicating some error. Also cell does not leave edit mode. Also I get lot of binding errors in output window. So, I know that my binding is incorrect. Can somebody help me to bind Combobox inside a datagrid?

Update:

If I use the SelectedValuePath as below :

<ComboBox ItemsSource="{Binding DataContext.GroupsCollection, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"
          SelectedValue="{Binding ParentID}" SelectedValuePath="{Binding GroupID}"
          DisplayMemberPath="GroupName" />

Then the error goes away and cell also leaves edit mode. But then TextBlock(which is celltemplate) always remains empty.

解决方案

Solved it. I should not use Binding in SelectedValuePath. So, now my code should look something like :

<ComboBox ItemsSource="{Binding DataContext.GroupsCollection, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"
          SelectedValue="{Binding ParentID}" SelectedValuePath="GroupID"
          DisplayMemberPath="GroupName" />

Now problem is :

I get ID (but I want to have name instead of ID) of the SelectedValue of ComboBox after the edit mode is finished due to my binding of CellTemplate as below:

<DataGridTemplateColumn Header="Parent" Width="2*">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding ParentID}" />
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
    <DataGridTemplateColumn.CellEditingTemplate>
        <DataTemplate>
            <ComboBox ItemsSource="{Binding DataContext.GroupsCollection, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"
                      SelectedValue="{Binding ParentID}" SelectedValuePath="GroupID"
                      DisplayMemberPath="GroupName" />
        </DataTemplate>
    </DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>

So I created a converter as below :

public class GroupIDToGroupName : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value != null)
        {
            SampleDBContext sampleDBContext = new SampleDBContext();
            return (from g in sampleDBContext.Groups
                    where g.GroupID == (int)value
                    select g.GroupName).FirstOrDefault();
        }
        else
        {
            return "";
        }
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        SampleDBContext sampleDBContext = new SampleDBContext();
        return (from g in sampleDBContext.Groups
                where g.GroupName == (string)value
                select g.GroupID).FirstOrDefault();
    }
}

And I declared that converter in App.xaml as :

<self:GroupIDToGroupName x:Key="GroupIDToGroupNameConveerter" />

Now, my Cell template looks like :

<TextBlock Text="{Binding ParentID, Converter={StaticResource GroupIDToGroupNameConveerter}}" />

I don't know that I have solved my problem in the right way or not. But its working!!!!

If anybody has a good idea then please share...........

这篇关于如何在数据网格内绑定ComboBox?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆