⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 datalistview.cs

📁 Linux 恢复盘制作工具 process调用busybox dd实现写*.img镜像
💻 CS
📖 第 1 页 / 共 2 页
字号:
/*
 * DataListView - A data-bindable listview
 *
 * Author: Phillip Piper
 * Date: 27/09/2008 9:15 AM
 *
 * Change log:
 * 2009-01-18   JPP  - Boolean columns are now handled as checkboxes
 *                   - Auto-generated columns would fail if the data source was 
 *                     reseated, even to the same data source
 * v2.0.1
 * 2009-01-07   JPP  - Made all public and protected methods virtual 
 * 2008-10-03   JPP  - Separated from ObjectListView.cs
 * 
 * Copyright (C) 2006-2008 Phillip Piper
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * If you wish to use this code in a closed source application, please contact phillip_piper@bigfoot.com.
 */

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing.Design;
using System.Windows.Forms;

namespace BrightIdeasSoftware
{

    /// <summary>
    /// A DataListView is a ListView that can be bound to a datasource (which would normally be a DataTable or DataView).
    /// </summary>
    /// <remarks>
    /// <para>This listview keeps itself in sync with its source datatable by listening for change events.</para>
    /// <para>If the listview has no columns when given a data source, it will automatically create columns to show all of the datatables columns.
    /// This will be only the simplest view of the world, and would look more interesting with a few delegates installed.</para>
    /// <para>This listview will also automatically generate missing aspect getters to fetch the values from the data view.</para>
    /// <para>Changing data sources is possible, but error prone. Before changing data sources, the programmer is responsible for modifying/resetting
    /// the column collection to be valid for the new data source.</para>
    /// <para>Internally, a CurrencyManager controls keeping the data source in-sync with other users of the data source (as per normal .NET
    /// behavior). This means that the model objects in the DataListView are DataRowView objects. If you write your own AspectGetters/Setters,
    /// they will be given DataRowView objects.</para>
    /// </remarks>
    public class DataListView : ObjectListView
    {
        /// <summary>
        /// Make a DataListView
        /// </summary>
        public DataListView()
            : base()
        {
        }

        #region Public Properties

        /// <summary>
        /// Get or set the DataSource that will be displayed in this list view.
        /// </summary>
        /// <remarks>The DataSource should implement either <see cref="IList"/>, <see cref="IBindingList"/>,
        /// or <see cref="IListSource"/>. Some common examples are the following types of objects:
        /// <list type="unordered">
        /// <item><see cref="DataView"/></item>
        /// <item><see cref="DataTable"/></item>
        /// <item><see cref="DataSet"/></item>
        /// <item><see cref="DataViewManager"/></item>
        /// <item><see cref="BindingSource"/></item>
        /// </list>
        /// <para>When binding to a list container (i.e. one that implements the
        /// <see cref="IListSource"/> interface, such as <see cref="DataSet"/>)
        /// you must also set the <see cref="DataMember"/> property in order
        /// to identify which particular list you would like to display. You
        /// may also set the <see cref="DataMember"/> property even when
        /// DataSource refers to a list, since <see cref="DataMember"/> can
        /// also be used to navigate relations between lists.</para>
        /// </remarks>
        [Category("Data"),
        TypeConverter("System.Windows.Forms.Design.DataSourceConverter, System.Design")]
        public virtual Object DataSource
        {
            get { return dataSource; }
            set {
                //THINK: Should we only assign it if it is changed?
                //if (dataSource != value) {
                dataSource = value;
                this.RebindDataSource(true);
                //}
            }
        }
        private Object dataSource;

        /// <summary>
        /// Gets or sets the name of the list or table in the data source for which the DataListView is displaying data.
        /// </summary>
        /// <remarks>If the data source is not a DataSet or DataViewManager, this property has no effect</remarks>
        [Category("Data"),
         Editor("System.Windows.Forms.Design.DataMemberListEditor, System.Design", typeof(UITypeEditor)),
         DefaultValue("")]
        public virtual string DataMember
        {
            get { return dataMember; }
            set {
                if (dataMember != value) {
                    dataMember = value;
                    RebindDataSource();
                }
            }
        }
        private string dataMember = "";

        #endregion

        #region Initialization

        private CurrencyManager currencyManager = null;

        /// <summary>
        /// Our data source has changed. Figure out how to handle the new source
        /// </summary>
        protected virtual void RebindDataSource()
        {
            RebindDataSource(false);
        }

        /// <summary>
        /// Our data source has changed. Figure out how to handle the new source
        /// </summary>
        protected virtual void RebindDataSource(bool forceDataInitialization)
        {
            if (this.BindingContext == null)
                return;

            // Obtain the CurrencyManager for the current data source.
            CurrencyManager tempCurrencyManager = null;

            if (this.DataSource != null) {
                tempCurrencyManager = (CurrencyManager)this.BindingContext[this.DataSource, this.DataMember];
            }

            // Has our currency manager changed?
            if (this.currencyManager != tempCurrencyManager) {

                // Stop listening for events on our old currency manager
                if (this.currencyManager != null) {
                    this.currencyManager.MetaDataChanged -= new EventHandler(currencyManager_MetaDataChanged);
                    this.currencyManager.PositionChanged -= new EventHandler(currencyManager_PositionChanged);
                    this.currencyManager.ListChanged -= new ListChangedEventHandler(currencyManager_ListChanged);
                }

                this.currencyManager = tempCurrencyManager;

                // Start listening for events on our new currency manager
                if (this.currencyManager != null) {
                    this.currencyManager.MetaDataChanged += new EventHandler(currencyManager_MetaDataChanged);
                    this.currencyManager.PositionChanged += new EventHandler(currencyManager_PositionChanged);
                    this.currencyManager.ListChanged += new ListChangedEventHandler(currencyManager_ListChanged);
                }

                // Our currency manager has changed so we have to initialize a new data source
                forceDataInitialization = true;
            }

            if (forceDataInitialization)
                InitializeDataSource();
        }

        /// <summary>
        /// The data source for this control has changed. Reconfigure the control for the new source
        /// </summary>
        protected virtual void InitializeDataSource()
        {
            if (this.Frozen || this.currencyManager == null)
                return;

            this.CreateColumnsFromSource();
            this.CreateMissingAspectGettersAndPutters();
            this.SetObjects(this.currencyManager.List);

            // If we have some data, resize the new columns based on the data available.
            if (this.Items.Count > 0) {
                foreach (ColumnHeader column in this.Columns) {
                    if (column.Width == 0)
                        this.AutoResizeColumn(column.Index, ColumnHeaderAutoResizeStyle.ColumnContent);
                }
            }
        }

        /// <summary>
        /// Create columns for the listview based on what properties are available in the data source
        /// </summary>
        /// <remarks>
        /// <para>This method will not replace existing columns.</para>
        /// </remarks>
        protected virtual void CreateColumnsFromSource()
        {
            if (this.currencyManager == null || this.Columns.Count != 0)
                return;

            PropertyDescriptorCollection properties = this.currencyManager.GetItemProperties();
            if (properties.Count == 0)
                return;

            bool hasBooleanColumns = false;
            for (int i = 0; i < properties.Count; i++) {
                PropertyDescriptor property = properties[i];

                // Relationships to other tables turn up as IBindibleLists. Don't make columns to show them.
                // CHECK: Is this always true? What other things could be here? Constraints? Triggers?
                if (property.PropertyType == typeof(IBindingList))
                    continue;

                // Create a column
                OLVColumn column = new OLVColumn(property.DisplayName, property.Name);
                if (property.PropertyType == typeof(bool) || property.PropertyType == typeof(CheckState)) {
                    hasBooleanColumns = true;
                    column.TextAlign = HorizontalAlignment.Center;
                    column.Width = 32;
                    column.AspectName = property.Name;
                    column.CheckBoxes = true;
                    if (property.PropertyType == typeof(CheckState))
                        column.TriStateCheckBoxes = true;
                } else {
                    column.Width = 0; // zero-width since we will resize it once we have some data

                    // If our column is a BLOB, it could be an image, so assign a renderer to draw it.
                    // CONSIDER: Is this a common enough case to warrant this code?
                    if (property.PropertyType == typeof(System.Byte[]))
                        column.Renderer = new ImageRenderer();
                }
                column.IsEditable = !property.IsReadOnly;

                // Add it to our list
                this.Columns.Add(column);
            }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -