我要实现的目标:我想拥有一个数据表,其中的不同类型的行具有不同的属性。一个示例是DataTable末尾的求和行(一旦工作,将有更多行)。
受this question描述扩展DataRow类(不是可接受的类)的两个答案的启发,我实现了以下内容:
public class ProjectEffortTable : DataTable
{
public ProjectEffortTable() : base() { }
public ProjectEffortTable(String TableName) : base(TableName) { }
protected ProjectEffortTable(System.Runtime.Serialization.SerializationInfo Info, System.Runtime.Serialization.StreamingContext Context) : base (Info, Context) { }
public ProjectEffortTable(String TableName, String TableNamespace) : base(TableName, TableNamespace) { }
protected override Type GetRowType()
{
return typeof(ProjectEffortRow);
}
protected override DataRow NewRowFromBuilder(DataRowBuilder Builder)
{
return new ProjectEffortRow(Builder);
}
}
public class ProjectEffortRow : DataRow
{
public ProjectEffortRow (DataRowBuilder Builder) : base (Builder)
{
}
public Boolean IsSum { get; set; }
}
使用以下代码,我可以添加一个新的求和行:
var SumRow = ProjectEfforts.NewRow() as ProjectEffortRow;
SumRow.IsSum = true;
// calculate sums for all month columns
foreach (DataColumn Column in ProjectEfforts.Columns)
{
Decimal Sum = 0;
foreach (DataRow CurrentRow in ProjectEfforts.Rows)
{
if (CurrentRow[Column] is Double)
{
Sum += Convert.ToDecimal(CurrentRow[Column]);
}
}
SumRow[Column] = Decimal.Truncate(Sum);
}
ProjectEfforts.Rows.Add(SumRow);
问题:数据表对象可以由用户操作(使用DataGridView),并且我需要将这些更改保存到我的数据模型中的数据库中(不保存总和行)。
要检查更改是否具有以下功能:
Boolean CheckForChanges()
{
Boolean Changed = false;
var ProjectChanges = DataTableObject.GetChanges();
if (ProjectChanges != null)
{
for (var i = 0; i < ProjectChanges.Rows.Count; i++)
{
if (!(ProjectChanges.Rows[i] as ProjectEffortRow).IsSum)
{
Changed = true;
}
}
}
return Changed;
}
不幸的是,该方法始终返回true,因为似乎GetChanges()创建了一个新的DataTable,其中该属性的信息丢失了。
我不想做什么:我不想为每个属性在DataTable中添加列,因为这会将我的视图与数据模型紧密结合在一起。如果我为每个属性创建新列,则将在模型中执行此操作,并且需要在视图中隐藏所有这些列-我认为这很难看。
问题:是否可以通过某种方式创建一个包含自定义类型的DataRows的DataTable,以维护自定义属性?
在此先感谢您的帮助
答案 0 :(得分:0)
经过更多思考后,我找到了迄今为止可以正常使用的解决方案。我不确定它的缩放程度如何,但是对于求和行我还是很满意的。关键是还可以用自定义代码实现GetChanges,因为该函数中已知关于汇总行的信息。 这是我当前的实现:
public class ProjectEffortTable : DataTable
{
public ProjectEffortTable() : base() { }
public ProjectEffortTable(String TableName) : base(TableName) { }
protected ProjectEffortTable(System.Runtime.Serialization.SerializationInfo Info, System.Runtime.Serialization.StreamingContext Context) : base (Info, Context) { }
public ProjectEffortTable(String TableName, String TableNamespace) : base(TableName, TableNamespace) { }
protected override Type GetRowType()
{
return typeof(ProjectEffortRow);
}
protected override DataRow NewRowFromBuilder(DataRowBuilder Builder)
{
return new ProjectEffortRow(Builder);
}
public new ProjectEffortTable GetChanges()
{
var Changes = Clone() as ProjectEffortTable;
foreach (ProjectEffortRow CurrentRow in Rows)
{
if ((CurrentRow.RowState != DataRowState.Unchanged) && (!CurrentRow.IsSum))
{
Changes.ImportRow(CurrentRow);
}
}
if (Changes.Rows.Count == 0)
{
Changes = null;
}
return Changes;
}
public new ProjectEffortTable GetChanges(DataRowState RowStates)
{
var Changes = Clone() as ProjectEffortTable;
foreach (ProjectEffortRow CurrentRow in Rows)
{
if ((CurrentRow.RowState == RowStates) && (!CurrentRow.IsSum))
{
Changes.ImportRow(CurrentRow);
}
}
if (Changes.Rows.Count == 0)
{
Changes = null;
}
return Changes;
}
public void AddSumRow()
{
// add line with sum for each month column
var SumRow = NewRow() as ProjectEffortRow;
SumRow.IsSum = true;
Rows.Add(SumRow);
RecalculateSums();
}
public Boolean HasSumRow()
{
var SumRowFound = false;
if ((Rows[Rows.Count - 1] as ProjectEffortRow).IsSum)
{
SumRowFound = true;
}
return SumRowFound;
}
public void RemoveSumRow()
{
if (HasSumRow())
{
Rows[Rows.Count - 1].Delete();
}
}
private void RecalculateSums()
{
if (!HasSumRow())
{
throw new ApplicationException("Recalculation of sum triggered without sum row being present");
}
foreach (DataColumn Column in Columns)
{
Decimal Sum = 0;
foreach (ProjectEffortRow CurrentRow in Rows)
{
if ((CurrentRow[Column] is Double) && (!CurrentRow.IsSum))
{
Sum += Convert.ToDecimal(CurrentRow[Column]);
}
}
Rows[Rows.Count - 1][Column] = Decimal.Truncate(Sum);
}
}
}