?? datalistview.cs
字號(hào):
/*
* 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);
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -