using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Windows.Forms;
namespace DevComponents.DotNetBar.Charts
{
    ///
    /// DataBinding helper class
    ///
    public class DataBinder : IDisposable
    {
        #region Private variables
        private readonly ChartControl _ChartControl;
        private readonly BaseChart _Chart;
        private readonly BaseSeries _Series;
        private CurrencyManager _CurrencyManager;
        private PropertyDescriptorCollection _Pdc;
        private DataView _DataView;
        private BindingSource _BindingSource;
        private BindingSource _BaseBindingSource;
        private object _BaseDataSource;
        private string _BaseDataMember;
        private bool _NotificationAutogen;
        private bool _NotificationInProgress;
        private int _SeriesCount;
        #endregion
        ///
        /// DataBinding
        ///
        ///
        internal DataBinder(BaseChart chart)
        {
            _Chart = chart;
            _ChartControl = chart.ChartControl;
        }
        internal DataBinder(BaseSeries series)
        {
            _Series = series;
            _Chart = series.Parent as BaseChart;
            _ChartControl = _Chart.ChartControl;
        }
        #region Internal properties
        #region BaseDataMember
        internal string BaseDataMember
        {
            get { return (_BaseDataMember); }
            set { _BaseDataMember = value; }
        }
        #endregion
        #region BaseDataSource
        internal object BaseDataSource
        {
            get { return (_BaseDataSource); }
            set { _BaseDataSource = value; }
        }
        #endregion
        #region CurrencyManager
        internal CurrencyManager CurrencyManager
        {
            get { return (_CurrencyManager); }
            set
            {
                if (_CurrencyManager != value)
                {
                    if (_CurrencyManager != null)
                        _CurrencyManager.ListChanged -= CurrencyManagerListChanged;
                    _CurrencyManager = value;
                    _BaseBindingSource = null;
                    if (_CurrencyManager != null)
                    {
                        _Pdc = CurrencyManager.GetItemProperties();
                        _BaseBindingSource = _BaseDataSource as BindingSource;
                        _CurrencyManager.ListChanged += CurrencyManagerListChanged;
                    }
                    else
                    {
                        _Pdc = null;
                    }
                }
            }
        }
        #endregion
        #region DataView
        internal DataView DataView
        {
            get { return (_DataView); }
            set { _DataView = value; }
        }
        #endregion
        #region GetValue
        internal object GetValue(int index, string name)
        {
            if (CurrencyManager != null && _Pdc != null)
            {
                if ((uint)index < CurrencyManager.List.Count)
                {
                    object dataItem = CurrencyManager.List[index];
                    PropertyDescriptorCollection pdc = GetPdc(dataItem);
                    PropertyDescriptor pd = FindPropertyDescriptor(pdc, name);
                    if (pd != null)
                        return (pd.GetValue(dataItem));
                }
            }
            return (null);
        }
        #endregion
        #region Pdc
        internal PropertyDescriptorCollection Pdc
        {
            get { return (_Pdc); }
            set { _Pdc = value; }
        }
        #endregion
        #region RowCount
        internal int RowCount
        {
            get
            {
                if (CurrencyManager != null)
                    return (CurrencyManager.Count);
                return (0);
            }
        }
        #endregion
        #endregion
        #region Clear
        internal void Clear()
        {
            CurrencyManager = null;
        }
        #endregion
        #region DataConnect
        internal object DataConnect(object dataSource, string dataMember)
        {
            _BaseDataSource = dataSource;
            _BaseDataMember = dataMember;
            if (_BaseDataSource != null)
            {
                _BindingSource = _BaseDataSource as BindingSource;
                if (_BindingSource != null)
                {
                    BindingSource bs = _BindingSource.DataSource as BindingSource;
                    if (bs != null)
                    {
                        if (string.IsNullOrEmpty(_BindingSource.DataMember) == false)
                            _BaseDataMember = _BindingSource.DataMember;
                        else
                            _BindingSource = null;
                        while (bs.DataSource is BindingSource)
                            bs = (BindingSource)bs.DataSource;
                        DataSet dss = bs.DataSource as DataSet;
                        if (dss != null)
                        {
                            DataRelation dsr = dss.Relations[_BaseDataMember];
                            if (dsr != null)
                            {
                                _BaseDataSource = dss;
                                _BaseDataMember = dsr.ChildTable.TableName;
                            }
                        }
                    }
                    else
                    {
                        _BaseDataSource = _BindingSource.DataSource;
                        _BaseDataMember = _BindingSource.DataMember;
                    }
                }
                DataView = null;
                if (_BaseDataSource is DataSet)
                    return (AddDataSetTable((DataSet)_BaseDataSource, _BaseDataMember));
                if (_BaseDataSource is DataTable)
                    return (AddDataTable((DataTable)_BaseDataSource));
                if (_BaseDataSource is IListSource)
                    return (AddList(((IListSource)_BaseDataSource).GetList()));
                
                return (AddList(_BaseDataSource));
            }
            return (null);
        }
        #endregion
        #region AddList
        internal object AddList(object source)
        {
            bool autogen = _Chart.AutoGenSeriesCollection;
            if (_ChartControl.DoDataBindingStartEvent(_Chart, source, ref autogen) == false)
                return (AddList(source, autogen));
            return (null);
        }
        internal object AddList(object source, bool autogen)
        {
            if (_Series == null)
            {
                if (SetDataConnection(source, autogen) == true)
                    ProcessAddList(source, autogen);
            }
            else
            {
                SetDataConnection(source, false);
            }
            return (source);
        }
        #region ProcessAddList
        private void ProcessAddList(object source, bool autogen)
        {
            if (_Pdc != null)
            {
                if (autogen == true && _ChartControl.DesignerHosted == false)
                    AutoGenerateListSeries(source);
                foreach (ChartSeries series in _Chart.BaseSeries)
                    series.NeedToUpdateBindings = true;
            }
        }
        #region AutoGenerateListSeries
        private void AutoGenerateListSeries(object source)
        {
            string nameSeries = _Chart.DataPropertyNameSeries;
            string nameX = GetListNameX(nameSeries);
            CustomCollection namesY = GetListNamesY(nameSeries, nameX);
            if (string.IsNullOrEmpty(nameSeries) == true)
                AutoGenListSeriesSingle(nameX, namesY);
            else
                AutoGenListSeriesMultiple(source, nameSeries, nameX, namesY);
        }
        #region AutoGenListSeriesSingle
        private void AutoGenListSeriesSingle(
            string nameX, CustomCollection namesY)
        {
            BaseSeries series = _Chart.GetNewSeries();
            series.DataPropertyNameX = nameX;
            series.DataPropertyNamesY = namesY;
            SetAutoSeriesId(series);
            _Chart.AddChartSeries(series);
        }
        #endregion
        #region AutoGenListSeriesMultiple
        private void AutoGenListSeriesMultiple(object source,
            string nameSeries, string nameX, CustomCollection namesY)
        {
            PropertyDescriptor pdSeries = FindListPd(nameSeries);
            if (pdSeries == null)
                throw new Exception("List series name not found (" + nameSeries + ")");
            object lastSeriesKey = null;
            IList list = source as IList;
            if (list != null)
            {
                for (int i = 0; i < list.Count; i++)
                {
                    object o = list[i];
                    if (o != null)
                    {
                        object seriesKey = pdSeries.GetValue(o);
                        if ((lastSeriesKey != null) && (seriesKey != lastSeriesKey))
                            AddAutoGenSeries(lastSeriesKey, nameSeries, nameX, namesY);
                        lastSeriesKey = seriesKey;
                    }
                }
                if (lastSeriesKey != null)
                    AddAutoGenSeries(lastSeriesKey, nameSeries, nameX, namesY);
            }
        }
        #endregion
        #region GetListNameX
        private string GetListNameX(string nameSeries)
        {
            string nameX = _Chart.DataPropertyNameX;
            if (string.IsNullOrEmpty(nameX) == false)
            {
                if (FindListPd(nameX) == null)
                    throw new Exception("Cannot find List Property (" + nameX + ")");
                return (nameX);
            }
            bool emptyNameSeries = string.IsNullOrEmpty(nameSeries);
            foreach (PropertyDescriptor pd in _Pdc)
            {
                if (IsAccessibleItem(pd) == true)
                {
                    if (emptyNameSeries == true || emptyNameSeries.Equals(pd.Name) == false)
                        return (pd.Name);
                }
            }
            throw new Exception("Cannot determine auto-assigned DataPropertyNameX.");
        }
        #endregion
        #region GetListNamesY
        private CustomCollection
            GetListNamesY(string nameSeries, string nameX)
        {
            CustomCollection namesY = _Chart.DataPropertyNamesY;
            if (namesY == null)
                namesY = new CustomCollection();
            if (namesY.Count == 0)
            {
                int countY = _Chart.GetAutoGenSeriesNameCount();
                foreach (PropertyDescriptor pd in _Pdc)
                {
                    if (IsAccessibleItem(pd) == true)
                    {
                        if ((nameSeries == null || nameSeries.Equals(pd.Name) == false)
                            && nameX.Equals(pd.Name) == false)
                        {
                            namesY.Add(pd.Name);
                            if (--countY == 0)
                                return (namesY);
                        }
                    }
                }
                throw new Exception("Cannot determine auto-assigned DataPropertyNamesY.");
            }
            return (namesY);
        }
        #endregion
        #region FindListPd
        private PropertyDescriptor FindListPd(string nameX)
        {
            foreach (PropertyDescriptor pd in _Pdc)
            {
                if (IsAccessibleItem(pd) == true)
                {
                    if (pd.Name.Equals(nameX) == true)
                        return (pd);
                }
            }
            return (null);
        }
        #endregion
        #region IsAccessibleItem
        private bool IsAccessibleItem(PropertyDescriptor pd)
        {
            if (pd.PropertyType.IsInterface == false)
            {
                if (IsNestedList(pd.PropertyType.Name) == false && IsVisibleItem(pd) == true)
                    return (true);
            }
            return (false);
        }
        #region IsNestedList
        private bool IsNestedList(string name)
        {
            return (name.Equals("List`1") || name.Equals("BindingList`1"));
        }
        #endregion
    
        #region IsVisibleItem
        private bool IsVisibleItem(PropertyDescriptor pd)
        {
            foreach (Attribute attr in pd.Attributes)
            {
                IsVisibleToChartControl dattr = attr as IsVisibleToChartControl;
                if (dattr != null)
                    return (dattr.Visible);
            }
            return (true);
        }
        #endregion
        #endregion
        #endregion
        #endregion
        #endregion
        #region AddDataSetTable
        internal object AddDataSetTable(DataSet dataSet, string dataMember)
        {
            if (string.IsNullOrEmpty(dataMember) && dataSet.Tables.Count > 0)
                dataMember = dataSet.Tables[0].TableName;
            if (string.IsNullOrEmpty(dataMember) == false)
                return (AddDataTable(dataSet.Tables[dataMember]));
            return (null);
        }
        #endregion
        #region AddDataTable
        internal object AddDataTable(DataTable dt)
        {
            if (_Series == null)
            {
                bool autogen = _Chart.AutoGenSeriesCollection;
                if (_ChartControl.DoDataBindingStartEvent(_Chart, dt, ref autogen) == false)
                {
                    if (SetDataConnection(dt, autogen) == true)
                    {
                        if (CurrencyManager != null)
                            ProcessAddDataTable(dt, autogen);
                    }
                }
            }
            else
            {
                SetDataConnection(dt, false);
            }
            return (dt);
        }
        #region ProcessAddDataTable
        private void ProcessAddDataTable(DataTable dt, bool autogen)
        {
            if (autogen == true && _ChartControl.DesignerHosted == false)
                AutoGenerateDataTableSeries(dt);
            dt.DefaultView.RowFilter = "";
            DataView = dt.DefaultView;
            ChartBaseSeriesCollection baseSeries = _Chart.BaseSeries;
            foreach (BaseSeries series in baseSeries)
                series.NeedToUpdateBindings = true;
        }
        #region AutoGenerateDataTableSeries
        private void AutoGenerateDataTableSeries(DataTable dt)
        {
            string nameSeries = _Chart.DataPropertyNameSeries;
            string nameX = GetDataTableNameX(dt, nameSeries);
            CustomCollection namesY = GetDataTableNamesY(dt, nameSeries, nameX);
            if (string.IsNullOrEmpty(nameSeries) == true)
                AutoGenDataTableSeriesSingle(dt, nameX, namesY);
            else
                AutoGenDataTableSeriesMultiple(dt, nameSeries, nameX, namesY);
        }
        #region AutoGenDataTableSeriesSingle
        private void AutoGenDataTableSeriesSingle(
            DataTable dt, string nameX, CustomCollection namesY)
        {
            BaseSeries series = _Chart.GetNewSeries();
            series.DataPropertyNameX = nameX;
            series.DataPropertyNamesY = namesY;
            SetAutoSeriesId(series);
            _Chart.AddChartSeries(series);
        }
        #endregion
        #region AutoGenDataTableSeriesMultiple
        private void AutoGenDataTableSeriesMultiple(DataTable dt,
            string nameSeries, string nameX, CustomCollection namesY)
        {
            DataColumn dtSeries = FindDataColumn(dt, nameSeries);
            if (dtSeries == null)
                throw new Exception("DataTable series name not found (" + nameSeries + ")");
            object lastSeriesKey = null;
            for (int i = 0; i < CurrencyManager.Count; i++)
            {
                DataRowView view = CurrencyManager.List[i] as DataRowView;
                if (view != null)
                {
                    object seriesKey = view.Row.ItemArray[dtSeries.Ordinal];
                    if ((lastSeriesKey != null) && (seriesKey != lastSeriesKey))
                        AddAutoGenSeries(lastSeriesKey, nameSeries, nameX, namesY);
                    lastSeriesKey = seriesKey;
                }
            }
            if (lastSeriesKey != null)
                AddAutoGenSeries(lastSeriesKey, nameSeries, nameX, namesY);
        }
        #region AddAutoGenSeries
        private void AddAutoGenSeries(object seriesKey,
            string nameSeries, string nameX, CustomCollection namesY)
        {
            string name = seriesKey.ToString();
            if (FindChartSeries(name) == null)
            {
                BaseSeries series = _Chart.GetNewSeries();
                series.SeriesId = ++_SeriesCount;
                series.Name = name;
                series.SeriesKey = seriesKey;
                series.DataPropertyNameSeries = nameSeries;
                series.DataPropertyNameX = nameX;
                series.DataPropertyNamesY = namesY;
                _Chart.AddChartSeries(series);
            }
        }
        #endregion
        #endregion
        #region GetDataTableNameX
        private string GetDataTableNameX(DataTable dt, string nameSeries)
        {
            string nameX = _Chart.DataPropertyNameX;
            if (string.IsNullOrEmpty(nameX) == false)
            {
                if (FindDataColumn(dt, nameX) == null)
                    throw new Exception("Cannot find DataColumn (" + nameX + ")");
                return (nameX);
            }
            bool emptyNameSeries = string.IsNullOrEmpty(nameSeries);
            foreach (DataColumn dtColumn in dt.Columns)
            {
                if ((dtColumn.ColumnMapping & MappingType.Hidden) != MappingType.Hidden)
                {
                    if (emptyNameSeries == true || emptyNameSeries.Equals(dtColumn.ColumnName) == false)
                        return (dtColumn.ColumnName);
                }
            }
            throw new Exception("Cannot determine auto-assigned DataPropertyNameX.");
        }
        #endregion
        #region GetDataTableNamesY
        private CustomCollection 
            GetDataTableNamesY(DataTable dt, string nameSeries, string nameX)
        {
            CustomCollection namesY = _Chart.DataPropertyNamesY;
            if (namesY == null)
                namesY = new CustomCollection();
            if (namesY.Count == 0)
            {
                int countY = _Chart.GetAutoGenSeriesNameCount();
                foreach (DataColumn dtColumn in dt.Columns)
                {
                    if ((dtColumn.ColumnMapping & MappingType.Hidden) != MappingType.Hidden)
                    {
                        if ((nameSeries == null || nameSeries.Equals(dtColumn.ColumnName) == false)
                            && nameX.Equals(dtColumn.ColumnName) == false)
                        {
                            namesY.Add(dtColumn.ColumnName);
                            if (--countY == 0)
                                return (namesY);
                        }
                    }
                }
                throw new Exception("Cannot determine auto-assigned DataPropertyNamesY.");
            }
            return (namesY);
        }
        #endregion
        #endregion
        #region FindDataColumn
        private DataColumn FindDataColumn(DataTable dt, string name)
        {
            if (string.IsNullOrEmpty(name) == false)
            {
                foreach (DataColumn dtColumn in dt.Columns)
                {
                    if ((dtColumn.ColumnMapping & MappingType.Hidden) != MappingType.Hidden)
                    {
                        if (dtColumn.ColumnName.Equals(name) == true)
                            return (dtColumn);
                    }
                }
            }
            return (null);
        }
        #endregion
        #endregion
        #endregion
        #region SetAutoSeriesId
        private void SetAutoSeriesId(BaseSeries series)
        {
            series.SeriesId = ++_SeriesCount;
            series.Name = GetUniqueSeriesName(series);
        }
        #region GetUniqueSeriesName
        private string GetUniqueSeriesName(BaseSeries series)
        {
            string name = "Series" + series.SeriesId;
            while (FindChartSeries(name) != null)
                name += "*";
            return (name);
        }
        #endregion
        #endregion
        #region SetDataConnection
        private bool SetDataConnection(object dataSource, bool autogen)
        {
            ClearDataNotification(dataSource);
            if (_BindingSource != null || _ChartControl.BindingContext != null)
                SetDataNotification(dataSource, autogen);
            return (_NotificationInProgress == false);
        }
        #endregion
        #region SetDataNotification
        private void SetDataNotification(object dataSource, bool autogen)
        {
            ISupportInitializeNotification notification =
                dataSource as ISupportInitializeNotification;
            if (notification == null || notification.IsInitialized == true)
            {
                CurrencyManager = (_BindingSource != null)
                    ? _BindingSource.CurrencyManager
                    : _ChartControl.BindingContext[DataView ?? dataSource] as CurrencyManager;
            }
            else
            {
                CurrencyManager = null;
                if (_NotificationInProgress == false)
                {
                    _NotificationInProgress = true;
                    _NotificationAutogen = autogen;
                    notification.Initialized += DataSourceInitialized;
                }
            }
        }
        #endregion
        #region ClearDataNotification
        private void ClearDataNotification(object dataSource)
        {
            ISupportInitializeNotification notification =
                dataSource as ISupportInitializeNotification;
            if (notification != null && _NotificationInProgress == true)
            {
                notification.Initialized -= DataSourceInitialized;
                _NotificationInProgress = false;
                _NotificationAutogen = false;
            }
        }
        #endregion
        #region DataSourceInitialized
        private void DataSourceInitialized(object sender, EventArgs e)
        {
            ISupportInitializeNotification dataSource =
                _Chart.DataSource as ISupportInitializeNotification;
            if (dataSource != null)
            {
                _NotificationInProgress = false;
                dataSource.Initialized -= DataSourceInitialized;
                CurrencyManager =
                    _ChartControl.BindingContext[dataSource] as CurrencyManager;
                if (dataSource is DataTable)
                    ProcessAddDataTable((DataTable)dataSource, _NotificationAutogen);
                else
                    ProcessAddList(dataSource, _NotificationAutogen);
            }
        }
        #endregion
        #region GetPdc
        private PropertyDescriptorCollection GetPdc(object dataItem)
        {
            if (_Chart.EnableDiscreteBoundItems == false)
                return (_Pdc);
            if (dataItem != null)
                return (TypeDescriptor.GetProperties(dataItem.GetType()));
            return (null);
        }
        #endregion
        #region FindPropertyDescriptor
        private PropertyDescriptor FindPropertyDescriptor(
            PropertyDescriptorCollection pdc, string name)
        {
            if (pdc != null)
            {
                foreach (PropertyDescriptor pd in pdc)
                {
                    if (pd.Name.Equals(name) == true)
                        return (pd);
                }
            }
            return (null);
        }
        #endregion
        #region FindChartSeries
        private BaseSeries FindChartSeries(string name)
        {
            ChartBaseSeriesCollection baseSeries = _Chart.BaseSeries;
            foreach (BaseSeries series in baseSeries)
            {
                if (name.Equals(series.Name) == true)
                    return (series);
            }
            return (null);
        }
        #endregion
        #region LoadSeriesData
        internal void LoadSeriesData(BaseSeries series)
        {
            if (_BaseDataSource is DataSet)
                LoadDataSetTable((DataSet)_BaseDataSource, _BaseDataMember, series);
            else if (_BaseDataSource is DataTable)
                LoadDataTableSeriesData((DataTable)_BaseDataSource, series);
            else
                LoadListSeriesData(series);
        }
        #region LoadDataSetTable
        internal void LoadDataSetTable(DataSet dataSet, string dataMember, BaseSeries series)
        {
            if (string.IsNullOrEmpty(dataMember) && dataSet.Tables.Count > 0)
                dataMember = dataSet.Tables[0].TableName;
            if (string.IsNullOrEmpty(dataMember) == false)
                LoadDataTableSeriesData(dataSet.Tables[dataMember], series);
        }
        #endregion
        #region LoadDataTableSeriesData
        private void LoadDataTableSeriesData(DataTable dt, BaseSeries series)
        {
            DataColumn dtSeries = FindDataColumn(dt, series.DataPropertyNameSeries);
            DataColumn dtNameX = FindDataColumn(dt, series.DataPropertyNameX);
            if (dtNameX == null)
                throw new Exception("DataPropertyNameX (" + series.DataPropertyNameX + ") not present in DataTable.");
            DataColumn[] dtNamesY =
                new DataColumn[series.DataPropertyNamesY.Count];
            for (int i = 0; i < series.DataPropertyNamesY.Count; i++)
            {
                string name = series.DataPropertyNamesY[i];
                dtNamesY[i] = FindDataColumn(dt, name);
                if (dtNamesY[i] == null)
                    throw new Exception("DataPropertyNameY (" + name + ") not present in DataTable.");
            }
            if (dtSeries == null)
                LoadDataTableSeriesDataSingle(series, dt, dtNameX, dtNamesY);
            else
                LoadDataTableSeriesDataMultiple(series, dt, dtSeries, dtNameX, dtNamesY);
            _ChartControl.DoSeriesDataBindingCompleteEvent(_Chart, series, dt);
        }
        #region LoadDataTableSeriesDataSingle
        private void LoadDataTableSeriesDataSingle(
            BaseSeries series, DataTable dt, DataColumn dtNameX, DataColumn[] dtNamesY)
        {
            for (int i = 0; i < CurrencyManager.Count; i++)
            {
                DataRowView view = CurrencyManager.List[i] as DataRowView;
                if (view != null)
                    AddDataTableSeriesData(series, dt, dtNameX, dtNamesY, view);
            }
        }
        #endregion
        #region LoadDataTableSeriesDataMultiple
        private void LoadDataTableSeriesDataMultiple(BaseSeries series,
            DataTable dt, DataColumn dtSeries, DataColumn dtNameX, DataColumn[] dtNamesY)
        {
            for (int i = 0; i < CurrencyManager.Count; i++)
            {
                DataRowView view = CurrencyManager.List[i] as DataRowView;
                if (view != null)
                {
                    object seriesKey = view.Row.ItemArray[dtSeries.Ordinal];
                    if (seriesKey == series.SeriesKey || seriesKey.Equals(series.SeriesKey))
                        AddDataTableSeriesData(series, dt, dtNameX, dtNamesY, view);
                }
            }
        }
        #endregion
        #region AddDataTableSeriesData
        private void AddDataTableSeriesData(BaseSeries series,
            DataTable dt, DataColumn dtNameX, DataColumn[] dtNamesY, DataRowView view)
        {
            object valueX = view.Row.ItemArray[dtNameX.Ordinal];
            object[] valuesY = new object[dtNamesY.Length];
            for (int i = 0; i < dtNamesY.Length; i++)
            {
                DataColumn dtcol = dtNamesY[i];
                valuesY[i] = view.Row.ItemArray[dtcol.Ordinal];
            }
            series.AddSeriesPoint(valueX, valuesY, view);
        }
        #endregion
        #endregion
        #region LoadListSeriesData
        private void LoadListSeriesData(BaseSeries series)
        {
            object source = _BaseDataSource;
            PropertyDescriptor pdSeries = FindListPd(series.DataPropertyNameSeries);
            PropertyDescriptor pdNameX = FindListPd(series.DataPropertyNameX);
            if (pdNameX == null)
                throw new Exception("DataPropertyNameX (" + series.DataPropertyNameX + ") not present.");
            PropertyDescriptor[] pdNamesY =
                new PropertyDescriptor[series.DataPropertyNamesY.Count];
            for (int i = 0; i < series.DataPropertyNamesY.Count; i++)
            {
                string name = series.DataPropertyNamesY[i];
                pdNamesY[i] = FindListPd(name);
                if (pdNamesY[i] == null)
                    throw new Exception("DataPropertyNameY (" + name + ") not present.");
            }
            if (pdSeries == null)
                LoadListSeriesDataSingle(series, source, pdNameX, pdNamesY);
            else
                LoadListSeriesDataMultiple(series, source, pdSeries, pdNameX, pdNamesY);
            _ChartControl.DoSeriesDataBindingCompleteEvent(_Chart, series, source);
        }
        #region LoadListSeriesDataSingle
        private void LoadListSeriesDataSingle(
            BaseSeries series, object source, PropertyDescriptor pdNameX, PropertyDescriptor[] pdNamesY)
        {
            IList list = source as IList;
            if (list != null)
            {
                for (int i = 0; i < list.Count; i++)
                {
                    object o = list[i];
                    AddListSeriesData(series, o, pdNameX, pdNamesY);
                }
            }
        }
        #endregion
        #region LoadListSeriesDataMultiple
        private void LoadListSeriesDataMultiple(BaseSeries series,
            object source, PropertyDescriptor pdSeries, PropertyDescriptor pgNameX, PropertyDescriptor[] pdNamesY)
        {
            IList list = source as IList;
            if (list != null)
            {
                for (int i = 0; i < list.Count; i++)
                {
                    object o = list[i];
                    object seriesKey = pdSeries.GetValue(o);
                    if (seriesKey == series.SeriesKey || seriesKey.Equals(series.SeriesKey))
                        AddListSeriesData(series, o, pgNameX, pdNamesY);
                }
            }
        }
        #endregion
        #region AddListSeriesData
        private void AddListSeriesData(BaseSeries series,
            object o, PropertyDescriptor pdNameX, PropertyDescriptor[] pdNamesY)
        {
            object valueX = pdNameX.GetValue(o);
            object[] valuesY = new object[pdNamesY.Length];
            for (int i = 0; i < pdNamesY.Length; i++)
                valuesY[i] = pdNamesY[i].GetValue(o);
            series.AddSeriesPoint(valueX, valuesY, o);
        }
        #endregion
        #endregion
        #endregion
        #region CurrencyManagerListChanged
        void CurrencyManagerListChanged(object sender, ListChangedEventArgs e)
        {
            if (_CurrencyManager != null)
                _Chart.InvalidateLayout();
        }
        #endregion
        #region Dispose
        /// 
        /// Data Binder Dispose
        /// 
        public void Dispose()
        {
            CurrencyManager = null;
        }
        #endregion
    }
}