使用单独的数据库表

时间:2015-07-17 18:07:58

标签: c# wpf xaml combobox csla

我的第一个StackExchange问​​题,请告诉我是否有任何错误。

我将旧的winforms代码转换为WPF,并且我一直在倾斜它们。我大部分时间都成功了,但是我正在处理我的第一个涉及数据绑定的数据表。它似乎是最难转换的,因为绑定主要是在xaml而不是代码中处理。

作为补充说明,它使用CSLA,据我所知,这是一个类似于MVVM的代码结构(仍然在学习它们是什么)。

通过一些实验,我设法创建了一个正常运行的数据网格,但我需要将其中一个列作为组合框实现。它当前表示为数字(1-10),但我需要与数字相关的描述,该数字位于数据库的不同表中。
在将其切换到组合框之前最初显示的数字是不合格的。我希望这个值是组合框中当前选定的项目。

无法发布图片,所以我试图展示数据库表的结构:

modreview

  • reviewnum
  • intcaseno
  • newreferral
  • screendate
  • 合格
  • noneligibilityreason (这是制作组合框的那个)

noneligreason (这是与不合格原因一致的子表格)

  • noneligreasonid
  • noneligreasondesc

代码包含了这个函数,它似乎创建了一个集合,我认为应该是ItemsSource:

NERList.GetNameValueList();

至于ItemsSource,我想要所有的noneligreasondesc值。当然,还有一个问题就是让不合格的理由与非精神分析相匹配。我找到了this example,它似乎做了同样的事情,但没有数据库,而是使用类:

我试图复制这个,因为我认为它应该在我的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();
    }
}

}

当我从Data Sources中拖放时,大部分代码都是生成的,但后面代码中的最后一行是我认为我应该添加ItemsSource的地方。不确定它是否属于Loaded,但似乎它可能没问题。也不确定是否有办法在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中的数据操作。

我现在一直在寻找解决方案,并且找不到与我相似的案例。我不确定每个绑定属性是如何工作的以及它们在这种特定情况下的应用方式。最后不得不放弃并在这里开帐户。抱歉这个长度,但我想具体一点,并表明我已经有一段时间了。

请帮助!

1 个答案:

答案 0 :(得分:1)

这里有很多有用的信息,也是SO问题的良好开端。

鉴于您的XAML绑定:

<DataGridComboBoxColumn x:Name="noneligibilityreasonColumn" Width="SizeToHeader" Header="noneligibilityreason"
                                    ItemsSource="{Binding Source={StaticResource noneligibilityViewSource}}"
                                    SelectedValueBinding="{Binding noneligibilityreason}"
                                    DisplayMemberPath="Value"
                                    SelectedValuePath="Key"
                                        />

这就是说(对于DataGrid中的每一行 - 而DataSet中的DataTable中的modreview对象/行),组合框控件应使用noneligibilityViewSource它的可选项列表。

(我们暂时忽略Window_Loaded事件中项目来源的矛盾设置。

它还表示组合框的显示(在控件中以可视方式显示)应来自DisplayMemberPath中指定的“值”属性。这将对应于ItemSource指定的集合中的item的相同命名属性。

由于组合框的项目是由ItemSource绑定提供的,那么它将来自noneligibilityViewSource,因此下一个问题是noneligibilityViewSource内的内容是什么?

您已将其声明为此窗口的资源:

<CollectionViewSource x:Key="noneligibilityViewSource" Source="{Binding noneligreason, Source={StaticResource caseviewDataSet}}" />

以上说明CollectionViewSource实例(又名noneligibilityViewSource)来自noneligreason上名为caseviewDataSet的属性。鉴于DataSet的工作方式,我期待一个名为noneligreason的DataTable或一个具有附加属性的自定义DataSet。可能是前者。

现在,您在Window_Loaded事件中有相反的代码,它以编程方式将组合框的ItemSource设置为其他内容。具体到调用NERList.GetNameValueList();的结果。我说是矛盾的,因为XAML资源声明说这个不合格值列表来自DataSet上相应命名的属性,而事件中的代码表示使用CSLA业务对象列表。

你必须弄清楚你想要/应该使用哪一个。

PS:可能,如果DataSet中的noneligibility属性包含数据,则无需通过调用NERList.GetNameValueList();来再次访问数据库,因为您有数据可用。

一旦你确定哪个“来源”包含你的组合框的项目列表 - 即。 noneligreason中的caseviewDataSet DataTable或来自NERList.GetNameValueList();的调用返回的CSLA业务对象列表中的noneligreason DataTable - 只有这样才能知道哪个属性应该用于DisplayMemberPath以及哪个属性用于SelectedValuePath。

因此,如果组合框的ItemSource是根据声明的XAML而caseviewDataSet有另一个名为noneligreasonid的DataTable,那么你需要找出属性的名称。例如,它可能是noneligreasondescDisplayMemberPath,但它可能是其他内容,具体取决于表适配器的功能。您的绑定noneligreasondesc可以是SelectedValuePathnoneligreasonid可以是NERList.GetNameValueList();

如果组合框的ItemSource应该来自对DisplayMemberPath的调用,那么您需要确定返回的对象的属性名称是什么。根据命名惯例,我猜测它是“名称”和“值”,这意味着Value应该是SelectedValuePathName应该设置为SelectedValueBinding。猜测并不好,所以去看看那个对象,或者使用调试器来检查值。

modreview属性是指SelectedValuePath行对象上应包含所选组合框项目值的属性,具体来说,组合框项目中的SelectedValueBinding属性将应用于modreview实例上的<DataGridComboBoxColumn x:Name="noneligibilityreasonColumn" Width="SizeToHeader" Header="noneligibilityreason" ItemsSource="{Binding Source={StaticResource noneligibilityViewSource}}" SelectedValueBinding="{Binding noneligibilityreason}" DisplayMemberPath="noneligreasondesc" SelectedValuePath="noneligreasonid" /> 属性。

以下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="Value"
                                        SelectedValuePath="Name"
                                            />

new

希望有所帮助。