You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 13:03:30