0

在我的应用程序中,我有一个表格,其中包含组织内各个区域的数据,相关表格包含有关每个区域的统计数据。为简单起见,我将它们表示为:

____________          ________________          ________________
|Region    |          |RegionHasDemo |          |DemoCategories|
|          |1        *|              |*        1|              |
|-RegionID |----------|-RegionID     |----------|-CatID        |
|-City     |          |-CatID        |          |-SortOrder    |
|-Zip      |          |-Population   |          |-Archive      |
|-State    |          |______________|          |______________|
|__________|          

DemoCategories 表包含人口统计类型。例如,假设 RegionHasDemo 代表我所在地区的年龄人口。DemoCategories 中的 CatID 将是 Age20to30、Age20to40 等值,因此 RegionHasDemo 代表所有地区的年龄组人口。

在我的应用程序中,我想创建一个表单来添加区域数据以及所有相关数据。为此,我创建了两个绑定源,一个用于 RegionData,一个用于 RegionHasDemo,其中包含 RegionData 作为 DataSource。由于各种原因,我想通过将单个文本框绑定到 RegionHasDemoBindingSource 的 List 属性中包含的 DataRowViews 来输入 RegionHasDemo 的数据。注意,我不想使用网格视图。

这是每次 RegionData 的 Current 属性更改时我用来绑定到文本框的代码:

注意:表名与我的示例不同,RegionData = UNITS; RegionHasDemo = UnitExp; DemoCategories = CatExp。

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Data.OleDb; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Diagnostics; namespace DBsample { public partial class Form1 : Form { private DataTable DataSource; private string relatedTableName; /// <summary> /// Holsd the values needed to define my text box rows and /// relate them to the table containing their human readable /// names, sort order, and active record status. /// </summary> private struct textBoxRow { public string Key { get; set; } public TextBox TBox { get; set; } public Label NameLabel { get; set; } public string Name { get; set; } public int Value { get; set; } } textBoxRow[] rows; public Form1() { InitializeComponent(); DataSource = injuryDB.UnitExp; relatedTableName = "CatExpUnitExp"; } private void Form1_Load(object sender, EventArgs e) { this.uNITSTableAdapter.Fill(this.injuryDB.UNITS); this.catExpTableAdapter1.Fill(this.injuryDB.CatExp); this.unitExpTableAdapter1.Fill(this.injuryDB.UnitExp); // Fill data table // Associate them in the struct in sorted order // Get a list of categories DataTable catTable = DataSource.ParentRelations[relatedTableName].ParentTable; // Sort them while leaving out the ones we don't want List<DataRow> tbr = (from r in catTable.AsEnumerable() where r.Field<bool>("ActiveRecord") orderby r.Field<int>("SortOrder") select r).ToList(); // The rows we are going to show rows = new textBoxRow[tbr.Count]; tableLayoutPanel1.RowStyles.Clear(); int rowIndex = 0; // Create rows and add them to the form foreach (DataRow r in tbr) { textBoxRow tRow = new textBoxRow(); Label lbl = new Label(); lbl.Text = r.Field<string>("CatName"); TextBox tb = new TextBox(); tRow.Key = r.Field<string>("Category"); tRow.Name = r.Field<string>("CatName"); tRow.TBox = tb; tRow.NameLabel = lbl; tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.AutoSize)); tableLayoutPanel1.Controls.Add(tRow.NameLabel, 0, rowIndex); tableLayoutPanel1.Controls.Add(tRow.TBox, 1, rowIndex); rows[rowIndex] = tRow; rowIndex++; } // Refresh the bindings in the text boxes when the current item changes unitCatExpBindingSource.CurrentItemChanged += currentItemChanged; currentItemChanged(null, null); } private void uNITSBindingNavigatorSaveItem_Click(object sender, EventArgs e) { bool validated = this.Validate(); if(validated == true) Debug.WriteLine("Validated data to be saved"); else Debug.WriteLine("Did not validate data to be saved"); this.uNITSBindingSource.EndEdit(); int recordsUpdated = this.tableAdapterManager.UpdateAll(this.injuryDB); Debug.WriteLine(string.Format("{0} records were changed", recordsUpdated)); } private void currentItemChanged(object sender, EventArgs e) { if (rows == null) return; // For some reason I have to pass this into the bindingSource's find method instead of a // straight string of the column name. It has something to do with the fact that we are // binding to a data relation instead of a DataTable i think. Wadded through so many forums for this... PropertyDescriptor pdc = unitCatExpBindingSource.CurrencyManager.GetItemProperties()["Cat"]; // Rebind each text box row foreach (textBoxRow tBoxRow in rows) { tBoxRow.TBox.DataBindings.Clear(); // If the record doesn't exist then that means the population for that group is zero tBoxRow.TBox.Text = "0"; //tbr.TBox.Leave -= existingRecordTBoxChanged; //tbr.TBox.Leave -= nonExistingRecordTBoxChanged; // Get the index of the source I want to bind to using the text int bindingIndex = unitCatExpBindingSource.Find(pdc, tBoxRow.Key); //object bs = unitCatExpBindingSource[bindingIndex]; if (bindingIndex >= 0) { Binding b = tBoxRow.TBox.DataBindings.Add("Text", unitCatExpBindingSource[bindingIndex], "Jumps", true); } else { // TODO: Create an event that adds a new to the demo table if number not 0 } } } // TODO: for this to work the delete options of the relationships // for Units -> category tables need to be set to cascade private void existingRecordTBoxChanged(object sender, EventArgs e) { TextBox tBox = (TextBox)sender; if (tBox.Text == "" || tBox.Text == "0") { //DataRow d = (DataRow)tBox.DataBindings[0].DataSource; } } private void nonExistingRecordTBoxChanged(object sender, EventArgs e) { TextBox tBox = (TextBox)sender; if (!(tBox.Text == "" || tBox.Text == "0")) { // TODO: Add record to the database } } } <code>

我的问题是,尽管当我的绑定似乎可以正常查看时,即当我浏览单元时文本框会发生变化。更改不会保存到数据库中。我在文本框中所做的更改将保留在 DataSet 中(当我离开记录并返回时它们保持不变)但是当我保存 dataSet 时关闭表单并再次打开它,更改就消失了。就好像没有通知数据集这些值已更改。此外,如果我将相关数据放在自定义文本框列表旁边的数据网格中,我可以从 DataGridView 修改数据,并且可以保存数据。此外,当我更改 TextBoxes 中的数据时,新值将显示在 DataGridView 中,但仍不会保存...

我想知道我用来将文本框绑定到数据的方法是否正确。意思是,我可以以包含在 Binding 源中的 DataRowView 的形式绑定数据,并期望它的行为与我直接使用绑定源的行为相同吗?

非常感谢您的帮助。我希望我已经提供了足够的信息让你继续。请记住,此代码示例来自原型。我知道这不是最佳做法。也就是说,我将不胜感激任何建设性的批评。

4

2 回答 2

1

经过多次试验和错误,我发现了问题。问题是我将文本框绑定到 DataRowView 对象。我不确定,但我认为 DataRowView 只能在 GridView 或 ListView 组件中专门使用。在我的项目中,我想将每个 DataRowView 单独绑定到单独的文本框,这会导致问题,因为 DataRowViews 似乎共享某种绑定属性,因此只有一个文本框被正确绑定。解决方案是从 DataRowView 中提取 DataRow 对象并将文本框绑定到该对象。如果有人对数据绑定上下文中 DataRows 和 DataRowViews 之间的差异有任何意见,将不胜感激。

于 2012-10-22T18:40:21.067 回答
0

我在组合框中有同样的问题,我已经解决了。我的代码看起来像

<sdk:DataGridTemplateColumn Width="150" Header="EstimateIOName">
                <sdk:DataGridTemplateColumn.CellEditingTemplate>
                    <DataTemplate>
                        <ComboBox x:Name="cbo" ItemsSource="{StaticResource IOList}" SelectedValue="{Binding Path=EstimateIOName,Mode=TwoWay}" SelectedValuePath="EstimateIOName"  SelectionChanged="cbo_SelectionChanged" DropDownClosed="cbo_DropDownClosed" ></ComboBox>
                    </DataTemplate>
                </sdk:DataGridTemplateColumn.CellEditingTemplate>
            </sdk:DataGridTemplateColumn>


            <sdk:DataGridTemplateColumn Width="180" Header="Selected EstimatedIOName" IsReadOnly="True">
                <sdk ataGridTemplateColumn.CellEditingTemplate>
                    <DataTemplate>
                        <TextBlock x:Name="cbo1" Text="{Binding Path=EstimateIOName,Mode=TwoWay}"></TextBlock>
                    </DataTemplate>
                </sdk:DataGridTemplateColumn>

我的代码背后看起来像

LoadOperation<ATDueDate> Load1 = context1.Load<ATDueDate>(context1.GetATDueDatesByEntityQuery("I"));
        Load1.Completed += (s, ea) =>
        {
            this.DataContext = Load1.Entities;
            comboBox2.ItemsSource = Load1.Entities.Select(a => a.PackageName.Substring(1,2)).Distinct();
        };

按钮点击

private void button1_Click(object sender, RoutedEventArgs e)
    {

        context1.SubmitChanges();

        MessageBox.Show("Changes Saved");
    }
于 2012-10-16T09:16:23.960 回答