使用单独的数据库表在 DataGridComboBoxColumn 中设置 ItemSource
本文关键字:DataGridComboBoxColumn 设置 ItemSource 单独 数据库 | 更新日期: 2023-09-27 18:03:11
我的第一个StackExchange问题,如果我做错了什么,请告诉我。
我正在将旧的 winforms 代码转换为 WPF,并在此过程中将它们都倾斜。 我大部分时间都很成功,但我正在处理我的第一个涉及数据绑定的数据表。 这似乎是最难转换的事情,因为绑定主要在 xaml 而不是代码中处理。
作为附加说明,它使用 CSLA,据我了解,这是一种类似于 MVVM 的代码结构(仍在学习这些是什么(。
通过一些实验,我设法创建了一个功能正常的数据网格,但我需要将其中一列实现为组合框。 它目前表示为数字(1-10(,但我需要与数字一起的描述,该描述位于数据库中的不同表中。
在将其切换到组合框之前最初显示的数字是 不合格原因。 我希望此值是组合框中当前选定的项目。
无法发布图像,因此这是我尝试显示数据库表结构的尝试:
模组评论
- 评论
- 因卡斯诺
- 新推荐
- 屏幕日期
- 资格
- 不合格原因(这是要制作成组合框的原因(
(这是与不合格原因一致的子表(
- Noneligreasonid
- 非资格原因
代码包含此函数,它似乎创建了一个集合,我认为应该是 ItemsSource:
NERList.GetNameValueList();
至于ItemsSource,我想要所有非限定原因desc值。 当然,还有一个问题是让不合格原因与非资格原因相匹配。 我发现了这个例子,它似乎做了同样的事情,但没有数据库,而是使用类:
我试图复制它,因为我认为它应该在我的 XAML 中工作:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfTestProject" x:Class="WpfTestProject.MainWindow"
Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded">
<Window.Resources>
<local:caseviewDataSet x:Key="caseviewDataSet"/>
<CollectionViewSource x:Key="modreviewViewSource"
Source="{Binding modreview, Source={StaticResource caseviewDataSet}}"/>
<CollectionViewSource x:Key="noneligibilityViewSource"
Source="{Binding noneligreason, Source={StaticResource caseviewDataSet}}"/>
</Window.Resources>
<Grid DataContext="{StaticResource modreviewViewSource}">
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<DataGrid x:Name="modreviewDataGrid"
RowDetailsVisibilityMode="VisibleWhenSelected"
ItemsSource="{Binding}"
EnableRowVirtualization="True"
AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn x:Name="reviewnumColumn" Width="SizeToHeader" Header="reviewnum" Binding="{Binding reviewnum}"/>
<DataGridTextColumn x:Name="intcasenoColumn" Width="SizeToHeader" Header="intcaseno" Binding="{Binding intcaseno}"/>
<DataGridCheckBoxColumn x:Name="newreferralColumn" Width="SizeToHeader" Header="newreferral" Binding="{Binding newreferral}"/>
<DataGridTemplateColumn x:Name="screendateColumn" Width="Auto" Header="screendate">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<DatePicker SelectedDate="{Binding screendate, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridCheckBoxColumn x:Name="eligibleColumn" Width="SizeToHeader" Header="eligible" Binding="{Binding eligible}"/>
<DataGridComboBoxColumn x:Name="noneligibilityreasonColumn" Width="SizeToHeader" Header="noneligibilityreason"
ItemsSource="{Binding Source={StaticResource noneligibilityViewSource}}"
SelectedValueBinding="{Binding noneligibilityreason}"
DisplayMemberPath="Value"
SelectedValuePath="Key"
/>
</DataGrid.Columns>
</DataGrid>
</Grid>
以及背后的代码:
using CslaFactoryBusinessObjects;
...
namespace WpfTestProject
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
WpfTestProject.caseviewDataSet caseviewDataSet = ((WpfTestProject.caseviewDataSet)(this.FindResource("caseviewDataSet")));
// Load data into the table modreview. You can modify this code as needed.
WpfTestProject.caseviewDataSetTableAdapters.modreviewTableAdapter caseviewDataSetmodreviewTableAdapter = new WpfTestProject.caseviewDataSetTableAdapters.modreviewTableAdapter();
caseviewDataSetmodreviewTableAdapter.Fill(caseviewDataSet.modreview);
System.Windows.Data.CollectionViewSource modreviewViewSource = ((CollectionViewSource)(this.FindResource("modreviewViewSource")));
modreviewViewSource.View.MoveCurrentToFirst();
noneligibilityreasonColumn.ItemsSource = NERList.GetNameValueList();
}
}
}
大部分代码都是在我从数据源拖放时生成的,但后面代码的最后一行是我认为应该添加 ItemsSource 的位置。不确定它是否属于已加载,但似乎在那里可能没问题。 也不确定是否有办法在 XAML 中执行此操作。
我意识到我在 XAML 和代码中重复了设置 ItemsSource,但两者都无法正常工作,因此我同时包含这两个选项以显示我尝试过的选项。
最后,我想我应该显示我试图在 WPF 转换中模拟的旧 winforms 代码(不确定这是否足够代码(。 我认为它使用隐藏的组合框来设置绑定,然后将其添加到表中:
//from Program.cs used in setupModRvwGrdHdr()
public static void ListControlBinding(ref UltraCombo comboBox, object lkupdataSource, string displayMember,
string valueMember, object objDataSource, string objProp) {
comboBox.DataSource = lkupdataSource;
comboBox.DisplayMember = displayMember;
if (!string.IsNullOrEmpty(valueMember))
comboBox.ValueMember = valueMember;
if (objDataSource != null)
comboBox.DataBindings.Add("Value", objDataSource, objProp);
}
//from the code for the specific winform
private void setupModRvwGrdHdr() {
cbNonEligReason.DataBindings.Clear();
grdModReviews.DataSource = bsModRvws;
Program.ListControlBinding(ref cbNonEligReason, NERList.GetNameValueList(), "Value", "Key", bsModRvws,
"NonEligibleReasonIDStr");
cbNonEligReason.DisplayLayout.Bands[0].Columns["Key"].Hidden = true;
cbNonEligReason.DisplayLayout.Bands[0].Columns["Value"].Header.Caption = "Noneligiblity Reason";
grdModReviews.DisplayLayout.Bands[0].Columns["reviewnum"].CellActivation = Activation.NoEdit;
grdModReviews.DisplayLayout.Bands[0].Columns["intcaseno"].Hidden = true;
grdModReviews.DisplayLayout.Bands[0].Columns["noneligibilityreason"].Hidden = true;
grdModReviews.DisplayLayout.Bands[0].Columns["screendate"].Hidden = false;
grdModReviews.DisplayLayout.Bands[0].Columns["screendate"].Header.Caption = "Date of Screen";
grdModReviews.DisplayLayout.Bands[0].Columns["screendate"].Width = 100;
grdModReviews.DisplayLayout.Bands[0].Columns["screendate"].EditorComponent = dteModRvwDate;
grdModReviews.DisplayLayout.Bands[0].Columns["eligible"].Hidden = false;
grdModReviews.DisplayLayout.Bands[0].Columns["eligible"].Header.Caption = "Eligible";
grdModReviews.DisplayLayout.Bands[0].Columns["eligible"].Width = 70;
grdModReviews.DisplayLayout.Bands[0].Columns["NonEligibleReasonIDStr"].Hidden = false;
grdModReviews.DisplayLayout.Bands[0].Columns["NonEligibleReasonIDStr"].Header.Caption =
"Reason for Noneligibility";
grdModReviews.DisplayLayout.Bands[0].Columns["NonEligibleReasonIDStr"].Width = 250;
grdModReviews.DisplayLayout.Bands[0].Columns["NonEligibleReasonIDStr"].EditorComponent = cbNonEligReason;
grdModReviews.DisplayLayout.Bands[0].Columns["NonEligibleReasonIDStr"].Nullable =
Infragistics.Win.UltraWinGrid.Nullable.Nothing;
}
这是一个相当大的程序,CslaFactoryBusinessObjects类中可能有一些有用的函数,但我认为我应该学习如何做到这一点,以便更好地理解WPF中的数据操作。
几天来我一直在寻找解决方案,但还没有找到与我足够相似的案例。 我只是不确定每个绑定属性的工作原理以及它们在这种特定情况下的应用方式。 最后不得不认输,在这里做一个账户。 很抱歉太长了,但我想具体一点,表明我已经有一段时间了。
请帮忙!
这里有很多有用的信息,也是 SO 问题的良好开端。
给定 XAML 绑定:
<DataGridComboBoxColumn x:Name="noneligibilityreasonColumn" Width="SizeToHeader" Header="noneligibilityreason"
ItemsSource="{Binding Source={StaticResource noneligibilityViewSource}}"
SelectedValueBinding="{Binding noneligibilityreason}"
DisplayMemberPath="Value"
SelectedValuePath="Key"
/>
这的意思是(对于 DataGrid 中的每一行 - 这反过来又是数据集内 DataTable 之外的modreview
对象/行(组合框控件应将noneligibilityViewSource
用于其可选项列表。
(让我们暂时忽略Window_Loaded
事件中项目源的矛盾设置(。
它还说,对于组合框的显示(在控件中直观地显示的内容(应来自DisplayMemberPath
中指定的"Value"属性。这将对应于 ItemSource
指定的集合中的项中的相同命名属性。
由于组合框的项目是由 ItemSource 绑定提供的,因此它将来自noneligibilityViewSource
,所以下一个问题是这个noneligibilityViewSource
里面有什么?
您已将其声明为此窗口的资源:
<CollectionViewSource x:Key="noneligibilityViewSource" Source="{Binding noneligreason, Source={StaticResource caseviewDataSet}}" />
上面指出,CollectionViewSource 实例(又名 noneligibilityViewSource
(来自caseviewDataSet
上名为 noneligreason
的属性。鉴于数据集的工作方式,我希望有一个名为noneligreason
的DataTable,或者一个带有附加属性的自定义数据集。可能是前者。
现在,Window_Loaded
事件中有矛盾的代码,该代码以编程方式将组合框的 ItemSource 设置为其他内容。特别是调用NERList.GetNameValueList();
的结果。我之所以说矛盾,是因为 XAML 资源声明说此不合格值列表来自数据集上相应命名的属性,而事件中的代码说使用 CSLA 业务对象列表。
你必须弄清楚你想/应该使用哪一个。
PS:很可能,如果 DataSet 中的 nonequiability 属性包含数据,则无需通过调用 NERList.GetNameValueList();
来再次访问数据库的性能损失,因为您已经有可用的数据。
一旦您确定了哪个"源"包含组合框的项目列表 - 即caseviewDataSet
中的noneligreason
DataTable 或调用 NERList.GetNameValueList();
返回的 CSLA 业务对象列表 - 只有这样,您才能知道哪个属性应该用于 DisplayMemberPath 以及哪个属性用于 SelectedValuePath。
因此,如果组合框的 ItemSource 符合声明的 XAML,并且 caseviewDataSet 具有另一个名为 noneligreason
的数据表,那么您需要从中找出属性的名称。例如,它可以是 noneligreasonid
和 noneligreasondesc
,但它可能是其他东西,具体取决于表适配器的作用。然后可以noneligreasondesc
绑定的DisplayMemberPath
,然后可以noneligreasonid
SelectedValuePath
。
如果组合框的 ItemSource 应再次来自对NERList.GetNameValueList();
的调用,则需要确定返回对象的属性名称是什么。从命名约定中,我猜测它是"名称"和"值",这意味着DisplayMemberPath
应该Value
,SelectedValuePath
应该设置为 Name
.猜测是没有好处的,所以去看看那个对象,或者使用调试器检查值。
SelectedValueBinding
属性是指modreview
行对象上应包含所选组合框项的值的属性,具体而言,组合框项中的 SelectedValuePath
属性将应用于modreview
实例上的 SelectedValueBinding
属性。
下面的 MSDN 文档应该可以帮助您了解 DataGridComboBoxColumn 上的各种属性的用途。 https://msdn.microsoft.com/en-us/library/system.windows.controls.datagridcomboboxcolumn(v=vs.110(.aspx
例如,XAML 可以更改为以下两个声明之一:
<DataGridComboBoxColumn x:Name="noneligibilityreasonColumn" Width="SizeToHeader" Header="noneligibilityreason"
ItemsSource="{Binding Source={StaticResource noneligibilityViewSource}}"
SelectedValueBinding="{Binding noneligibilityreason}"
DisplayMemberPath="noneligreasondesc"
SelectedValuePath="noneligreasonid"
/>
或
<DataGridComboBoxColumn x:Name="noneligibilityreasonColumn" Width="SizeToHeader" Header="noneligibilityreason"
ItemsSource="{Binding Source={StaticResource noneligibilityViewSource}}"
SelectedValueBinding="{Binding noneligibilityreason}"
DisplayMemberPath="Value"
SelectedValuePath="Name"
/>
希望有帮助。