知识库

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
    }
}
版权所有 © 2011 CopyRight 南宁珞德信息技术有限公司 代码:商务部 设计:新1站