WPF中DataGrid内ComboBox如何显示关联表列表并绑定行数据值
问题描述
我正在使用C# WPF结合SQL Server数据库开发,现有一个以Factor表为ItemsSource的DataGrid。该DataGrid内包含一个ComboBox,其数据源为与Factor表关联的Commodity表。
需求:希望此ComboBox下拉时显示Commodity表的列表,但选中的值需对应DataGrid当前行的对应字段值。
已尝试的代码
XAML代码
<Window x:Class="ComboDataWPF.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:ComboDataWPF" mc:Ignorable="d" x:Name="InvoiceWindow" Title="MainWindow" Height="450" Width="800" WindowStartupLocation="CenterScreen" Loaded="Window_Loaded"> <Grid> <DataGrid x:Name="MainDataGrid" AutoGenerateColumns="False" ItemsSource="{Binding WHOLE_DATA_FACTOR, UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}"> <DataGrid.Columns> <DataGridTextColumn Header="Customer Name" Width="120" Binding="{Binding CustomerName, UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" /> <DataGridTemplateColumn Header="The Product Customer Bought" Width="200"> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <ComboBox x:Name="ComboBox_Commodity" ItemsSource="{Binding ElementName=InvoiceWindow ,Path=TheCommodityCombo_DATA}" DisplayMemberPath="CommodityName" SelectedValuePath="CommodityCode" IsTextSearchEnabled="True" IsEditable="True" SelectedIndex="0" BorderBrush="#FFADEEB4" Background="{x:Null}" BorderThickness="1"> <!--For ComboBox_Commodity ↑--> <!--SelectedValue="{Binding The selected value of each combo box is proportional and based on the value of that row in the datagrid}"--> <ComboBox.ItemsPanel> <ItemsPanelTemplate> <VirtualizingStackPanel VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.VirtualizationMode="Recycling"/> </ItemsPanelTemplate> </ComboBox.ItemsPanel> </ComboBox> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> </DataGrid.Columns> </DataGrid> </Grid> </Window>
C#后台代码
public partial class MainWindow : Window { MyerEntities dbms = new MyerEntities(); /// <summary> /// For Factor Table /// </summary> public class MyCustomModel_Factor { public long? NUMBER { get; set; } public string CustomerName { get; set; } public long? CommodityCode { get; set; } } public ObservableCollection<MyCustomModel_Factor> WHOLE_DATA_FACTOR { get; set; } = new ObservableCollection<MyCustomModel_Factor>(); /// <summary> /// For Commodity Table for ComboBox Items /// </summary> public ObservableCollection<MyCustomModel_Commodity> TheCommodityCombo_DATA { get; set; } = new ObservableCollection<MyCustomModel_Commodity>(); public class MyCustomModel_Commodity { public long CommodityCode { get; set; } public string CommodityName { get; set; } } public MainWindow() { InitializeComponent(); DataContext = this; } private void Window_Loaded(object sender, RoutedEventArgs e) { //Filling DataGrid by ObservableCollection WHOLE_DATA_FACTOR.Clear(); var RST = dbms.Database.SqlQuery<MyCustomModel_Factor>("SELECT * FROM Factor").ToList(); foreach (var item in RST) { WHOLE_DATA_FACTOR.Add(item); } //Filling ComboBox from another table that is related to Factor table TheCommodityCombo_DATA.Clear(); var RST2 = dbms.Database.SqlQuery<MyCustomModel_Commodity>("SELECT CommodityCode, CommodityName FROM dbo.Commodity").ToList(); foreach (var item2 in RST2) { TheCommodityCombo_DATA.Add(item2); } } }
解决方案
只需修改ComboBox的绑定配置,移除硬编码的选中项,添加与当前行字段的双向绑定即可:
1. 修改XAML中的ComboBox代码
去掉SelectedIndex="0",添加SelectedValue的双向绑定:
<ComboBox x:Name="ComboBox_Commodity" ItemsSource="{Binding ElementName=InvoiceWindow ,Path=TheCommodityCombo_DATA}" DisplayMemberPath="CommodityName" SelectedValuePath="CommodityCode" IsTextSearchEnabled="True" IsEditable="True" SelectedValue="{Binding CommodityCode, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" BorderBrush="#FFADEEB4" Background="{x:Null}" BorderThickness="1">
2. 可选:实现属性变化通知(推荐)
为MyCustomModel_Factor类实现INotifyPropertyChanged接口,确保属性修改时UI能自动更新:
using System.ComponentModel; using System.Runtime.CompilerServices; public class MyCustomModel_Factor : INotifyPropertyChanged { private long? _number; public long? NUMBER { get => _number; set { _number = value; OnPropertyChanged(); } } private string _customerName; public string CustomerName { get => _customerName; set { _customerName = value; OnPropertyChanged(); } } private long? _commodityCode; public long? CommodityCode { get => _commodityCode; set { _commodityCode = value; OnPropertyChanged(); } } public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
原理说明
SelectedValuePath="CommodityCode"指定ComboBox选项中用于匹配的字段,与Factor表的CommodityCode字段对应。SelectedValue="{Binding CommodityCode, ...}"建立当前DataGrid行数据与ComboBox选中值的双向绑定,加载时自动匹配对应选项,修改选中值也会同步回数据模型。- 移除
SelectedIndex="0"是因为硬编码会强制选中第一个选项,覆盖原有数据的对应值。
内容的提问来源于stack exchange,提问作者Mojtabah
相关产品推荐
相关产品推荐

