将TextBox绑定到BindingSource IList属性中的特定DataRowView



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

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

人口统计类别表包含人口统计的类型。例如,假设RegionHasDemo代表了我所在地区的年龄人口。DemoCategories中的CatID值应为Age20-30、Age20-40。。。使得RegionHasDemo表示所有区域的年龄组人口。

在我的应用程序中,我想创建一个表单来添加区域数据以及所有相关数据。为此,我创建了两个绑定源,一个用于RegionData,另一个用于包含RegionData作为DataSource的RegionHasDemo。由于各种原因,我希望通过将各个文本框绑定到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>

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

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

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

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

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

<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");
}

相关内容

  • 没有找到相关文章

最新更新