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

WPF中如何访问DataGrid内ComboBox的属性及解决绑定为空问题

问题:DataGrid模板列中ComboBox绑定为空且无法后台访问

我希望在DataGrid的DataGridTemplateColumn内的ComboBox中显示数据,但绑定后控件为空,尝试在后台代码中填充数据,却无法通过名称访问该ComboBox。试过切换到GridView,但操作难度比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"
        Title="MainWindow" Height="450" Width="800" WindowStartupLocation="CenterScreen" Loaded="Window_Loaded">
    
    <Grid>
        <DataGrid x:Name="MainDataGrid" AutoGenerateColumns="False" ItemsSource="{Binding ALLMYDATA, UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}">

            <DataGrid.Columns>
                <DataGridTextColumn Header="The Name :" Width="120" Binding="{Binding NAMES, UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" />

                <DataGridTemplateColumn Header=" Name and Code " Width="150">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <ComboBox x:Name="ComboBox1"
                                      ItemsSource="{Binding ALLMYDATA, UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}"
                                      SelectedValuePath="{Binding CODE, UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}"
                                      DisplayMemberPath="{Binding NAMES, UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}"
                                      IsTextSearchEnabled="True"
                                      IsEditable="True"
                                      SelectedIndex="0"  BorderBrush="#FFADEEB4" Background="{x:Null}" BorderThickness="1">
                                
                                <ComboBox.ItemsPanel>
                                    <ItemsPanelTemplate>
                                        <VirtualizingStackPanel VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.VirtualizationMode="Recycling"/>
                                    </ItemsPanelTemplate>
                                </ComboBox.ItemsPanel>
                            </ComboBox>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>

        </DataGrid>
    </Grid>
</Window>

后台C#代码

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace ComboDataWPF
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        MyerEntities dbms = new MyerEntities();
        public ObservableCollection<MyCustomModel> ALLMYDATA { get; set; } = new ObservableCollection<MyCustomModel>();
        public class MyCustomModel
        {
            public int CODE { get; set; }
            public string NAMES { get; set; }
        }
        public MainWindow()
        {
            InitializeComponent();
            DataContext = this;
        }
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            ALLMYDATA.Clear();
            var RST = dbms.Database.SqlQuery<MyCustomModel>("SELECT CODE,NAMES FROM TCOD_ANBAR").ToList();
            foreach (var item in RST)
            {
                ALLMYDATA.Add(item);
            }
        }
    }
}

问题分析与解决

一、ComboBox为空的原因及修复

ComboBox绑定失败的核心问题是数据上下文错误:

  • DataGrid的ItemsSource绑定的是ALLMYDATA,因此模板列中的每个元素的DataContext是单个MyCustomModel对象,而非窗口本身。
  • 原来的ItemsSource="{Binding ALLMYDATA}"会去当前行的MyCustomModel里找ALLMYDATA属性,而该属性不存在,导致绑定失效。

同时,SelectedValuePath和DisplayMemberPath的用法错误:这两个属性是指定属性名称的字符串,不需要用Binding语法,直接写属性名即可。

修复后的ComboBox XAML:

<ComboBox x:Name="ComboBox1"
          ItemsSource="{Binding DataContext.ALLMYDATA, RelativeSource={RelativeSource AncestorType=Window}, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
          SelectedValuePath="CODE"
          DisplayMemberPath="NAMES"
          IsTextSearchEnabled="True"
          IsEditable="True"
          SelectedIndex="0"  
          BorderBrush="#FFADEEB4" 
          Background="{x:Null}" 
          BorderThickness="1">
  • 用RelativeSource指定绑定源为窗口的DataContext,从而正确获取全局的ALLMYDATA集合。
  • 修正SelectedValuePath和DisplayMemberPath为直接属性名。

二、后台访问ComboBox的方法

由于ComboBox在DataTemplate内部,每个DataGrid行都会生成一个实例,无法直接通过x:Name在后台访问。可以通过以下两种方式处理:

1. 推荐:通过绑定操作(MVVM方式)

将ComboBox需要操作的属性(如SelectedItem、ItemsSource)绑定到ViewModel(这里是MainWindow)的属性,避免直接操作控件。比如在MyCustomModel中添加SelectedItem属性,绑定到ComboBox的SelectedItem,即可在后台通过数据集合操作选中状态。

2. 直接查找控件(仅在必要时使用)

如果必须直接操作ComboBox实例,可以通过DataGrid的ItemContainerGenerator找到对应行,再查找控件:

private void AccessComboBox()
{
    // 获取指定索引的行(示例为第0行)
    var row = MainDataGrid.ItemContainerGenerator.ContainerFromIndex(0) as DataGridRow;
    if (row == null) return;

    // 获取模板列的单元格内容
    var cellContent = MainDataGrid.Columns[1].GetCellContent(row);
    if (cellContent == null) return;

    // 查找ComboBox
    var comboBox = (cellContent as FrameworkElement).FindName("ComboBox1") as ComboBox;
    if (comboBox != null)
    {
        // 执行操作,比如更新ItemsSource
        comboBox.ItemsSource = ALLMYDATA;
    }
}

注意:DataGrid默认开启虚拟化,未加载的行无法通过此方法获取,需确保行已生成后再调用。


内容的提问来源于stack exchange,提问作者Mojtabah

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 07:15:41