C# 如何使用网格本身以外的其他DataContext使用ComboBoxColumn创建DataGrid?

C# 如何使用网格本身以外的其他DataContext使用ComboBoxColumn创建DataGrid?,c#,wpf,datagrid,wpfdatagrid,datagridcomboboxcolumn,C#,Wpf,Datagrid,Wpfdatagrid,Datagridcomboboxcolumn,我是WPF的新手,我被困在这个问题上,我找不到任何能帮助我解决问题的东西 我正在尝试创建DataGrid,我想在其中比较导入文件中的多人和数据库中的人。我的想法是用ComboboxColumn(数据库中的人员列表)创建(人员数据的)被告知数据网格。我的主要问题是,由于用户在上一个窗口中的选择,比较和填充组合框的人可能会有所不同。完成一些数据库工作后,我将窗口中的两个选项保存为: personList //list of Person objects to populate com

我是WPF的新手,我被困在这个问题上,我找不到任何能帮助我解决问题的东西

我正在尝试创建DataGrid,我想在其中比较导入文件中的多人和数据库中的人。我的想法是用ComboboxColumn(数据库中的人员列表)创建(人员数据的)被告知数据网格。我的主要问题是,由于用户在上一个窗口中的选择,比较和填充组合框的人可能会有所不同。完成一些数据库工作后,我将窗口中的两个选项保存为:

        personList //list of Person objects to populate combobox
        pisList //list of Person objects to fill DataGrid
现在我不知道如何将这两个值都获取到DataGrid,所以我也填充了ComboboxColumn。我尝试将其中一个值作为整个窗口的DataContext,第二个作为datagrid ItemsSource

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {        
        Database db = new Database();
        List<Person> personList = (...); 
        List<Person> pislist = (...);
        dgPlayers.ItemsSource = impTeam.PlaysInSquad.ToList();
        wPlayers.DataContext = personList;
    }
private void Window\u已加载(对象发送方,路由目标)
{        
数据库db=新数据库();
列表个人列表=(…);
列表pislist=(…);
dgPlayers.ItemsSource=impTeam.playsinsteam.ToList();
wPlayers.DataContext=个人列表;
}
当我在一个数据网格中获得这两个数据网格时,我不幸失败了,我创建了两个单独的数据网格,但仍然可以让它工作

    <DataGrid Name="dgPlayers" AutoGenerateColumns="False">
        <DataGrid.Columns>
            <DataGridTextColumn Header="Number" Binding="{Binding Number}" IsReadOnly="True"/>
            <DataGridTextColumn Header="Name" Binding="{Binding Person.Name}" IsReadOnly="True"/>
            <DataGridTextColumn Header="Surname" Binding="{Binding Person.Surname}" IsReadOnly="True"/>
            <DataGridTextColumn Header="Role" Binding="{Binding IDRole}" IsReadOnly="True"/>
        </DataGrid.Columns>
    </DataGrid>

    <DataGrid Name="dgList" AutoGenerateColumns="False">
        <DataGrid.Columns>
            <DataGridComboBoxColumn x:Name="List" ItemsSource="{Binding DataContext.Person}" DisplayMemberPath="Name"/>               
        </DataGrid.Columns>
    </DataGrid>

第一个DataGrid还可以,但我仍然无法正确填充ComboxColumn+,我希望在一个DataGrid而不是两个DataGrid中看到这一点

编辑
尽管我之前已经尝试过,但没有成功,这个线程的解决方案在第三次尝试后对我有效:

DataGridColumns
DataGrid
不在同一个可视化树中,因此它不会从其父级继承
DataContext
。这就是为什么不能使用简单的绑定语法来绑定它。然而,要实现这一点,有许多变通办法

我将在这里列出其中两个:

首先利用
Freezable
Freezable对象的神奇之处在于它可以继承DataContext,即使它们不在可视或逻辑树中。你可以在这里了解更多

在项目中添加此类:

public class BindingProxy : Freezable
{
    #region Overrides of Freezable

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

    #endregion

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

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

<DataGrid>
   <DataGrid.Resources>
      <local:BindingProxy x:Key="proxy" Data="{Binding}" />
   </DataGrid.Resources>
   <DataGrid.Columns>
      <DataGridComboBoxColumn ItemsSource="{Binding Source={StaticResource proxy}}"/>
   </DataGrid.Columns>
</DataGrid>
现在您可以像这样绑定DataGrid:

<TextBlock Visibility="Collapsed" x:Name="txt"/>
<DataGrid>
   <DataGrid.Columns>
      <DataGridComboBoxColumn ItemsSource="{Binding Source={x:Reference txt}}"/>
   </DataGrid.Columns>
</DataGrid>

要单独绑定组合框,只需将组合框的集合设置为资源。这样,您的组合框就不需要担心数据网格的数据上下文是什么

<Window.Resources>
    <CollectionContainer x:Key="PeopleItemsSource" Collection="{Binding personList}" />
<!-- or <CollectionViewSource x:Key="PeopleItemsSource" Source="{Binding personList}" /> -->
</Window.Resources>
<Grid>
    <DataGrid ItemsSource="{Binding pisList}">
        <DataGrid.Columns>
            <DataGridComboBoxColumn ItemsSource="{Binding Source={StaticResource PeopleItemsSource}}"/>
        </DataGrid.Columns>
    </DataGrid>
</Grid>


我从第二种方法开始,因为它对我来说似乎更容易。尽管我认为我理解这一点,但似乎我在实现方面遗漏了一些东西。完全按照上面所述完成了所有操作,但出现了以下错误:
对象引用未设置为对象的实例。
Textblock添加到DataGrid上方,我还在代码隐藏中添加了DataContext。有什么提示吗?第二种方法更好,但更好的方法是通过一个资源,而不是一个隐藏的UI元素。@LordTakkera-resource在应用于某个元素之前不会继承DataContext。请注意,在我的回答中,我使用了Windows的资源,因此它会有窗口的数据上下文(我假设他想要这样做)你试过运行它吗
CollectionContainer
CollectionViewSource
不是ItemsSource DP的有效值。请注意,“pisList”和“personList”必须是窗口数据上下文对象(理想情况下是视图模型)上的公共属性,上述代码示例才能工作。不过,以编程方式设置它们的概念是相同的。
CollectionContainer
CollectionViewSource
不是
ItemsSource DP
的有效值。您是正确的,请参阅更新的答案(我的绑定未完成)@LordTakkera尝试运行此代码,但组合框仍然为空。将
pisList
personList
公开。问题似乎在于装订的方式<代码>dgPlayers.ItemsSource=(…).ToList()正确填充主数据网格<代码>“另一方面没有。Alos在加载的窗口末尾给出断点,
Collection=“{Binding personList}”“/>
显示为14人元素的列表,但在ComboboxColumn上没有结果。pisList和personList是数据上下文类的公共属性吗?此外,还需要将MainWindow类的datacontext设置为将这些列表作为公共属性的任何对象。如果没有正确的片段,则在运行时的输出窗口中会看到绑定异常。
<TextBlock Visibility="Collapsed" x:Name="txt"/>
<DataGrid>
   <DataGrid.Columns>
      <DataGridComboBoxColumn ItemsSource="{Binding Source={x:Reference txt}}"/>
   </DataGrid.Columns>
</DataGrid>
<Window.Resources>
    <CollectionContainer x:Key="PeopleItemsSource" Collection="{Binding personList}" />
<!-- or <CollectionViewSource x:Key="PeopleItemsSource" Source="{Binding personList}" /> -->
</Window.Resources>
<Grid>
    <DataGrid ItemsSource="{Binding pisList}">
        <DataGrid.Columns>
            <DataGridComboBoxColumn ItemsSource="{Binding Source={StaticResource PeopleItemsSource}}"/>
        </DataGrid.Columns>
    </DataGrid>
</Grid>