XWooo.UISmoothRefreshData,支持多线程修改的数据源
2012-02-06
其实DataBindSource包含这些功能了。只不过自己要求的功能不高,既然能满足要求,当然是越简单越好,所以还是自己写的比较好用……
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Windows.Forms;
using System.Collections;
using System.Reflection;
namespace XWooo
{
public class UISmoothRefreshData
{
public string FieldKey { get; set; }
public string[] FieldList { get; set; }
public Control UIControl { get; set; }
public DataTable Data { get; set; }
private Queue<UISmoothRefreshDataEvent> queue;
public const string FIELD_SOURCE_DATA = "UISmoothRefreshData_SourceData";
public const string FIELD_CHANGED_STATE = "UISmoothRefreshData_ChangedState";
#region 属性
private bool keepSort = true;
public bool KeepSort
{
get
{
return keepSort;
}
set
{
keepSort = value;
}
}
#endregion
//private Timer refresher;
/// <summary>
/// <para>不允许使用UISmoothRefreshData_SourceData作为字段名</para>
/// <para>不允许使用UISmoothRefreshData_ChangedState作为字段名</para>
/// </summary>
/// <param name="uiControl"></param>
/// <param name="fieldKey"></param>
/// <param name="fieldList"></param>
public UISmoothRefreshData(Control uiControl, string fieldKey, params string[] fieldList)
{
UIControl = uiControl;
FieldKey = fieldKey;
FieldList = fieldList;
Data = new DataTable();
Data.Columns.Add(fieldKey);
Data.PrimaryKey = new DataColumn[] { Data.Columns[0] };
foreach (string fieldItem in fieldList)
{
Data.Columns.Add(fieldItem);
}
Data.Columns.Add(FIELD_SOURCE_DATA, typeof(object));
Data.Columns.Add(FIELD_CHANGED_STATE, typeof(DataRowState));
queue = new Queue<UISmoothRefreshDataEvent>();
//refresher = new Timer();
//refresher.Interval = 500;
}
public void UpdateBy(object data)
{
lock (queue)
{
queue.Enqueue(new UISmoothRefreshDataEvent(data, UISmoothRefreshDataMethod.Update));
}
RefreshData();
}
public void ReplaceBy(object data)
{
lock (queue)
{
queue.Enqueue(new UISmoothRefreshDataEvent(data, UISmoothRefreshDataMethod.Replace));
}
RefreshData();
}
public delegate void DelegateRefreshData();
public void RefreshData()
{
if (UIControl.InvokeRequired)
{
DelegateRefreshData refreshData = new DelegateRefreshData(RefreshData);
UIControl.Invoke(refreshData);
}
else
{
//执行数据合并
UISmoothRefreshDataEvent evt = null;
while (queue.Count > 0)
{
//try
//{
lock (queue)
{
evt = queue.Dequeue();
}
if (evt != null)
{
//if (Data.Rows.Count > 0) return;
foreach (DataRow dr in this.Data.Rows)
{
dr[FIELD_CHANGED_STATE] = DataRowState.Unchanged;
}
#region 合并的数据为空
if (evt.Data == null)
{
Data.Clear();
continue;
}
#endregion
int i = 0; //更新进来的数据的遍历索引
int j = 0; //本地数据的遍历索引
int offset = 0; //本地数据对于更新进来的数据的偏移量
#region 合并的数据为DataTable
if (evt.Data is DataTable)
{
DataTable dt_in = (DataTable)evt.Data;
#region 如果要求保持顺序,则先检查顺序,顺序不OK,全部清除(待会会添加回去的)
if (keepSort)
{
if (dt_in.Rows.Count == this.Data.Rows.Count)
{
for (i = 0; i < dt_in.Rows.Count; i++)
{
object obj = dt_in.Rows[i][FieldKey];
if (this.Data.Rows[i][FieldKey].Equals(obj) == false)
{
this.Data.Rows.Clear();
break;
}
}
}
else
{
this.Data.Rows.Clear();
}
}
#endregion
for (i = 0; i < dt_in.Rows.Count; i++)
{
DataRow dr_in = dt_in.Rows[i];
object keyValue = dr_in[FieldKey];
DataRow dr = null;
for (j = 0; j < this.Data.Rows.Count; j++)
{
if (this.Data.Rows[j][FieldKey].Equals(keyValue))
{
dr = this.Data.Rows[j];
break;
}
}
if (dr == null)
{
dr = Data.NewRow();
}
foreach (DataColumn col in Data.Columns)
{
if (col.ColumnName == FIELD_SOURCE_DATA)
{
dr[col.ColumnName] = dr_in;
}
else
{
if (dt_in.Columns.IndexOf(col.ColumnName) > 0)
{
dr[col.ColumnName] = dr_in[col.ColumnName];
}
}
}
if (dr.RowState == DataRowState.Detached)
{
Data.Rows.Add(dr);
}
dr[FIELD_CHANGED_STATE] = DataRowState.Modified;
}
}
#endregion
#region 合并的数据为List
else if (evt.Data is IEnumerable)
{
List<object> dt_in = ((IEnumerable)evt.Data).OfType<object>().ToList();
Type type_in = dt_in.First().GetType();
PropertyInfo[] PropertyInfos = type_in.GetProperties();
#region 如果要求保持顺序,则先检查顺序,顺序不OK,全部清除(待会会添加回去的)
if (keepSort)
{
if (dt_in.Count == this.Data.Rows.Count)
{
for (i = 0; i < dt_in.Count; i++)
{
object obj = type_in.GetProperty(FieldKey).GetValue(dt_in[i], null);
if (this.Data.Rows[i][FieldKey].Equals(obj) == false)
{
this.Data.Rows.Clear();
break;
}
}
}
else
{
this.Data.Rows.Clear();
}
}
#endregion
for (i = 0; i < dt_in.Count; i++)
//foreach (object dr_in in dt_in)
{
object dr_in = dt_in[i];
object keyValue = type_in.GetProperty(FieldKey).GetValue(dr_in, null);
DataRow dr = null;
for (j = 0; j < this.Data.Rows.Count; j++)
{
if (this.Data.Rows[j][FieldKey].Equals(keyValue))
{
dr = this.Data.Rows[j];
break;
}
}
if (dr == null)
{
dr = Data.NewRow();
}
foreach (DataColumn col in Data.Columns)
{
if (col.ColumnName == FIELD_SOURCE_DATA)
{
dr[col.ColumnName] = dr_in;
}
else
{
PropertyInfo currPropertyInfo = PropertyInfos.FirstOrDefault(p => p.Name == col.ColumnName);
if (currPropertyInfo != null)
{
dr[col.ColumnName] = currPropertyInfo.GetValue(dr_in, null);
}
}
}
if (dr.RowState == DataRowState.Detached)
{
Data.Rows.Add(dr);
}
dr[FIELD_CHANGED_STATE] = DataRowState.Modified;
}
}
#endregion
#region 合并的数据是单项
else
{
Type type_in = evt.Data.GetType();
PropertyInfo[] PropertyInfos = type_in.GetProperties();
object keyValue = type_in.GetProperty(FieldKey).GetValue(evt.Data, null);
DataRow dr = Data.Rows.Find(keyValue);
[FS:Page]
if (dr == null)
{
dr = Data.NewRow();
}
foreach (DataColumn col in Data.Columns)
{
if (col.ColumnName == FIELD_SOURCE_DATA)
{
dr[col.ColumnName] = evt.Data;
}
else
{
PropertyInfo currPropertyInfo = PropertyInfos.FirstOrDefault(p => p.Name == col.ColumnName);
if (currPropertyInfo != null)
{
dr[col.ColumnName] = currPropertyInfo.GetValue(evt.Data, null);
}
}
}
if (dr.RowState == DataRowState.Detached)
{
Data.Rows.Add(dr);
}
dr[FIELD_CHANGED_STATE] = DataRowState.Modified;
}
#endregion
#region 如果是替换,要把没动过的数据删除
if (evt.Method == UISmoothRefreshDataMethod.Replace)
{
for (int n = 0; n < Data.Rows.Count; n++)
{
if (((DataRowState)Data.Rows[n][FIELD_CHANGED_STATE]) == DataRowState.Unchanged)
{
Data.Rows.RemoveAt(n);
n--;
}
}
}
#endregion
//Data.AcceptChanges();
}
//}
//catch (Exception ex)
//{
// ToolsLib.CLoggerTools.Debug2File("Program",
// "{3}.Tick:{0}{1}{2}",
// ex.Message,
// System.Environment.NewLine,
// ex.StackTrace,
// UIControl.Name);
//}
}
}
}
/// <summary>
/// 返回数据项
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="dataItem"></param>
/// <returns></returns>
public T GetDataItem<T>(object dataItem)
{
DataRow dataRow = null;
//if (dataItem is DataRow)
//{
dataRow = (DataRow)dataItem;
//}
//else
//{
// //new DataGridViewRow().DataBoundItem is DataRowView
//}
return (T)dataRow[FIELD_SOURCE_DATA];
}
}
public static class UISmoothRefreshDataFixDataGridView
{
public static object DataBoundItemByUISmoothRefreshData(this DataGridViewRow dtgRow)
{
if (dtgRow.DataBoundItem is DataRow)
{
DataRow dr = (DataRow)dtgRow.DataBoundItem;
return dr[UISmoothRefreshData.FIELD_SOURCE_DATA];
}
else if (dtgRow.DataBoundItem is DataRowView)
{
DataRowView drv = (DataRowView)dtgRow.DataBoundItem;
DataRow dr = drv.Row;
return dr[UISmoothRefreshData.FIELD_SOURCE_DATA];
}
return null;
}
}
public class UISmoothRefreshDataEvent
{
public object Data { get; set; }
public UISmoothRefreshDataMethod Method { get; set; }
public UISmoothRefreshDataEvent(object data, UISmoothRefreshDataMethod method)
{
Data = data;
Method = method;
}
}
public enum UISmoothRefreshDataMethod : int
{
Update = 0,
Replace = 1
}
}