C# WPF中DataGridComboBoxColumn默认值未显示问题求助
问题:WPF DataGridComboBoxColumn默认值仅在编辑模式显示,非编辑状态不加载
项目背景
原有连接SQL Server的MS Access 2003 ADP VBA项目,迁移至C# WPF,计划通过DataGrid直接将数据保存到SQL Server。
实现细节
- DataGrid的ItemsSource绑定
INVO_DATA_RASID_KHARID(ObservableCollection类型) - 包含
ANBAR_COLUMN(DataGridComboBoxColumn),其ItemsSource从SQL Server获取 - 默认值通过后台
FillALLComboboxes方法存入静态变量Baseknow.anbardef,模型类INVO_LST_RASID_KHARID_CSHARP的构造函数为ANBAR属性赋值该默认值
当前问题
ANBAR_COLUMN列的默认值仅在用户双击进入单元格编辑模式时才显示,DataGrid加载完成后默认值不显示,需要实现DataGrid加载完成时直接显示默认值,无需进入编辑模式。
提供的代码
XAML代码
<DataGrid x:Name="INVO_LST_RASID_SUB" EnableColumnVirtualization="True" EnableRowVirtualization="True" VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.VirtualizationMode="Recycling" ScrollViewer.CanContentScroll="False" KeyboardNavigation.TabNavigation="Contained" ItemsSource="{Binding INVO_DATA_RASID_KHARID}" Grid.Row="5" Margin="5,10" AutoGenerateColumns="False" FlowDirection="RightToLeft" SelectionUnit="FullRow" BorderThickness="1" > <DataGrid.Columns> <DataGridComboBoxColumn x:Name="ANBAR_COLUMN" MinWidth="80" Width="auto" Header=" انبار " SelectedValueBinding="{Binding ANBAR,UpdateSourceTrigger=PropertyChanged}" DisplayMemberPath="NAMES" SelectedValuePath="CODE"> <DataGridComboBoxColumn.EditingElementStyle> <Style TargetType="{x:Type ComboBox}"> <Setter Property="IsEditable" Value="True"/> </Style> </DataGridComboBoxColumn.EditingElementStyle> </DataGridComboBoxColumn> </DataGrid.Columns> </DataGrid>
窗口后台C#代码
//MainWindow: public partial class HEAD_LST_RASID : Window { public ObservableCollection<INVO_LST_RASID_KHARID_CSHARP> INVO_DATA_RASID_KHARID { get; set; } = new ObservableCollection<INVO_LST_RASID_KHARID_CSHARP>(); public HEAD_LST_RASID() { InitializeComponent(); this.DataContext = this; } public void FillALLComboboxes() { string RowSource_ANBAR = "SELECT CODE, NAMES FROM dbo.TCOD_ANBAR"; //Search for the default value if it exists var rst = dbms.Database.SqlQuery<int?>("SELECT ANBCO FROM dbo.OPANBACCESS WHERE (USERCO = " + Baseknow.USERCOD + " ) ORDER BY dbo.OPANBACCESS.RDF").ToList(); if (rst.Count > 0) { Baseknow.anbardef = (int)rst.FirstOrDefault(); } var ARST = dbms.Database.SqlQuery<Custom_TCODANBAR>(RowSource_ANBAR).ToList(); ANBAR_COLUMN.ItemsSource = ARST; } private void Window_Loaded(object sender, RoutedEventArgs e) { FillALLComboboxes(); var QRE_LST = dbms.Database.SqlQuery<INVO_LST_RASID_KHARID_CSHARP>($@"SELECT * FROM INVOICES").ToList(); INVO_DATA_RASID_KHARID?.Clear(); foreach (var item in QRE_LST) INVO_DATA_RASID_KHARID.Add(item); } }
模型类代码
//Model: public class CTABLES { public class INVO_LST_RASID_KHARID_CSHARP : INotifyPropertyChanged, ICloneable { public object Clone() { return this.MemberwiseClone(); } public INVO_LST_RASID_KHARID_CSHARP() { ANBAR = Baseknow.anbardef; } private int? _anbar; public int? ANBAR { get { return _anbar; } set { if (_anbar == value) return; _anbar = value; OnPropertyChanged("ANBAR"); } } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName = "") { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } }
解决方案
问题根源在于DataGridComboBoxColumn的非编辑状态(默认显示模板)不会自动根据SelectedValue匹配并显示对应的DisplayMember文本,需要自定义单元格模板来实现该逻辑。
方案1:替换为DataGridTemplateColumn,自定义显示与编辑模板
- 修改XAML中的
ANBAR_COLUMN为DataGridTemplateColumn,分别定义非编辑状态的显示模板和编辑状态的下拉框模板:
<DataGridTemplateColumn x:Name="ANBAR_COLUMN" MinWidth="80" Width="auto" Header=" انبار "> <!-- 非编辑状态显示模板 --> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <TextBlock Text="{Binding ANBAR, Converter={StaticResource AnbarCodeToNameConverter}}" /> </DataTemplate> </DataGridTemplateColumn.CellTemplate> <!-- 编辑状态模板 --> <DataGridTemplateColumn.CellEditingTemplate> <DataTemplate> <ComboBox ItemsSource="{Binding DataContext.AnbarList, RelativeSource={RelativeSource AncestorType=DataGrid}}" SelectedValue="{Binding ANBAR, UpdateSourceTrigger=PropertyChanged}" DisplayMemberPath="NAMES" SelectedValuePath="CODE" IsEditable="True"/> </DataTemplate> </DataGridTemplateColumn.CellEditingTemplate> </DataGridTemplateColumn>
- 添加转换器,用于将ANBAR的CODE值转换为对应的名称文本:
public class AnbarCodeToNameConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (value is int code && Baseknow.AnbarList != null) { var targetItem = Baseknow.AnbarList.FirstOrDefault(x => x.CODE == code); return targetItem?.NAMES ?? string.Empty; } return string.Empty; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } }
- 修改后台代码,将ANBAR列表存入可访问的位置(静态变量或窗口属性):
// 在窗口类中添加属性 public List<Custom_TCODANBAR> AnbarList { get; set; } public void FillALLComboboxes() { string RowSource_ANBAR = "SELECT CODE, NAMES FROM dbo.TCOD_ANBAR"; var rst = dbms.Database.SqlQuery<int?>("SELECT ANBCO FROM dbo.OPANBACCESS WHERE (USERCO = " + Baseknow.USERCOD + " ) ORDER BY dbo.OPANBACCESS.RDF").ToList(); if (rst.Count > 0) { Baseknow.anbardef = (int)rst.FirstOrDefault(); } // 保存列表到属性和静态变量 AnbarList = dbms.Database.SqlQuery<Custom_TCODANBAR>(RowSource_ANBAR).ToList(); Baseknow.AnbarList = AnbarList; }
- 在窗口资源中声明转换器:
<Window.Resources> <local:AnbarCodeToNameConverter x:Key="AnbarCodeToNameConverter"/> </Window.Resources>
额外注意事项
- 确保从数据库查询的
INVO_LST_RASID_KHARID_CSHARP对象中,若数据库的ANBAR字段为null,构造函数会正确赋值Baseknow.anbardef - 确认
Baseknow.anbardef对应的CODE值存在于AnbarList中,否则转换器会返回空文本
内容的提问来源于stack exchange,提问作者مجتبی حکیمیان
相关产品推荐
相关产品推荐

