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