如何在没有单元格模板的情况下使用DataGridComboBoxColumn
本文关键字:情况下 DataGridComboBoxColumn 单元格 | 更新日期: 2023-09-27 18:19:44
这应该是一件相当简单的事情我在这件事上绞尽脑汁太久了,
为什么ComboBox
控件将显示类别列表,而DataGridComboBoxColumn
控件在两者使用相同设置时拒绝显示类别列表
我是否必须为DataGridComboBoxColumn指定单元格模板才能使其工作,或者我在这里做错了什么?
复制的步骤很简单:
1.创建新的wpf项目并将其命名为WpfApplication10
2.将代码复制粘贴到MainWindow.xaml
和MainWindows.xaml.cs
中
3.运行项目-您会注意到ComboBox
显示值,而DataGridComboBoxColumn
不会显示值。
示例代码:
using System.Collections.ObjectModel;
using System.Windows;
namespace WpfApplication10
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public Vm TheVm;
public MainWindow()
{
TheVm = new Vm
{
VmCategories = new ObservableCollection<VmCategory>
{
new VmCategory { CategoryName="Category1" },
new VmCategory { CategoryName="Category2" },
new VmCategory { CategoryName="Category3" },
new VmCategory { CategoryName="Category4" },
new VmCategory { CategoryName="Category5" },
new VmCategory { CategoryName="Category6" }
},
VmUsers = new ObservableCollection<VmUser>
{
new VmUser { Name = "Gil" },
new VmUser { Name = "Dan" },
new VmUser { Name = "John" },
}
};
InitializeComponent();
DataContext = TheVm;
}
}
public class Vm
{
public ObservableCollection<VmCategory> VmCategories { get; set; }
public ObservableCollection<VmUser> VmUsers { get; set; }
}
public class VmUser
{
public string Name { get; set; }
public VmCategory VmCategoryInfo { get; set; }
}
public class VmCategory
{
public string CategoryName { get; set; }
}
}
示例XAML:
<Window x:Class="WpfApplication10.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication10"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525"
d:DataContext="{d:DesignInstance local:Vm, IsDesignTimeCreatable=True}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ComboBox Width="200" Height="40"
ItemsSource="{Binding DataContext.VmCategories, RelativeSource={RelativeSource AncestorType=Window}}"
DisplayMemberPath="CategoryName" />
<DataGrid Grid.Row="1"
ItemsSource="{Binding VmUsers}" AutoGenerateColumns="False"
CanUserAddRows="True" CanUserDeleteRows="True" AreRowDetailsFrozen="False" SelectionMode="Single">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding Name}" />
<DataGridComboBoxColumn Header="Category" Width="120"
SelectedItemBinding="{Binding VmCategoryInfo}"
ItemsSource="{Binding DataContext.VmCategories, RelativeSource={RelativeSource AncestorType=Window}}"
DisplayMemberPath="CategoryName"
/>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
重要更新
对于未来因同样问题而访问此页面的所有其他人,
如果你应用了解决方案,但它仍然没有解决你的问题-这意味着你有另一个问题导致了同样的问题-除非你很快就能解决,否则这是一个恶魔般的产物-我会解释:
就我而言,在更大的程序中,而不是我提供的示例中,
我需要解决的DataContext
位于TabItem
控件中,该控件本身不属于视觉树,因此它不起作用,因此实际上存在两个问题,一个是DataGridColumns
不在视觉树中,另一个是,TabItem
也不在视觉树中。。所以你应用了一个解决方案,但问题仍然存在,你认为这个解决方案有问题,而实际上你在不知不觉中处理了两个问题,导致了同一个错误
我最终通过创建一个网格来解决这个问题,该网格充当了保留TabItem
的DataContext
的代理元素。
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding Name}" />
<DataGridComboBoxColumn Header="Category" Width="120" SelectedItemBinding="{Binding VmCategoryInfo}"
DisplayMemberPath="CategoryName">
<DataGridComboBoxColumn.ElementStyle>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="ItemsSource" Value="{Binding Path=DataContext.VmCategories, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" />
</Style>
</DataGridComboBoxColumn.ElementStyle>
<DataGridComboBoxColumn.EditingElementStyle>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="ItemsSource" Value="{Binding Path=DataContext.VmCategories, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" />
</Style>
</DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>
</DataGrid.Columns>
由于DataGridComboBoxColumn
或任何其他支持的数据网格列不是数据网格可视化树的一部分,因此它们不会继承数据网格的DataContext。因为,它们不在可视化树中,所以任何使用RelativeSource获取DataContext的尝试都不起作用。
解决方案-您可以创建一个代理元素来绑定窗口的数据上下文;使用该代理元素来绑定DataGridComboBoxColumn
的ItemsSource。例如:
<Window x:Class="WpfApplication10.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication10"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525"
d:DataContext="{d:DesignInstance local:Vm, IsDesignTimeCreatable=True}">
<Grid>
<Grid.Resources>
<FrameworkElement x:Key="ProxyElement" DataContext="{Binding}"/>
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ComboBox Width="200" Height="40"
ItemsSource="{Binding DataContext.VmCategories, RelativeSource={RelativeSource AncestorType=Window}}"
DisplayMemberPath="CategoryName" />
<ContentControl Visibility="Collapsed" Content="{StaticResource ProxyElement}"></ContentControl>
<DataGrid Grid.Row="1"
ItemsSource="{Binding VmUsers}" AutoGenerateColumns="False"
CanUserAddRows="True" CanUserDeleteRows="True" AreRowDetailsFrozen="False" SelectionMode="Single">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding Name}" />
<DataGridComboBoxColumn Header="Category" Width="120"
SelectedItemBinding="{Binding VmCategoryInfo}"
ItemsSource="{Binding DataContext.VmCategories, Source={StaticResource ProxyElement}}"
DisplayMemberPath="CategoryName"
/>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>