先上效果图
1, 先写一个 GridCheckMarksSelection 类
class GridCheckMarksSelection
{
#region Fileds
RepositoryItemGridLookUpEdit _currentRepository;
protected ArrayList selection;
protected String checkColumnFieldName = "CheckMarkSelection";
RepositoryItemCheckEdit edit;
const Int32 CheckboxIndent = 4;
#endregion
#region Construct
public GridCheckMarksSelection(RepositoryItemGridLookUpEdit repository)
: this()
{
CurrentRepository = repository;
}
public RepositoryItemGridLookUpEdit CurrentRepository
{
get { return _currentRepository; }
set
{
if (_currentRepository != value)
{
Detach();
Attach(value);
}
}
}
public GridCheckMarksSelection()
{
selection = new ArrayList();
this.OnSelectionChanged();
}
#endregion
#region Attribute
public ArrayList Selection
{
get { return selection; }
set { selection = value; }
}
public Int32 SelectedCount { get { return selection.Count; } }
#endregion
#region GridSelect
public object GetSelectedRow(Int32 index)
{ return selection[index]; }
public Int32 GetSelectedIndex(object row)
{ return selection.IndexOf(row); }
public void ClearSelection(GridView currentView)
{
selection.Clear();
Invalidate(currentView);
OnSelectionChanged();
}
public void SelectAll(object sourceObject)
{
selection.Clear();
if (sourceObject != null)
{
if (sourceObject is ICollection)
selection.AddRange(((ICollection)sourceObject));
else
{
GridView currentView = sourceObject as GridView;
for (Int32 i = 0; i < currentView.DataRowCount; i++)
selection.Add(currentView.GetRow(i));
Invalidate(currentView);
}
}
this.OnSelectionChanged();
}
public delegate void SelectionChangedEventHandler(object sender, EventArgs e);
public event SelectionChangedEventHandler SelectionChanged;
public void OnSelectionChanged()
{
if (SelectionChanged != null)
{
EventArgs e = new EventArgs();
SelectionChanged(this, e);
}
}
public void SelectGroup(GridView currentView, Int32 rowHandle, bool select)
{
if (IsGroupRowSelected(currentView, rowHandle) && select) return;
for (Int32 i = 0; i < currentView.GetChildRowCount(rowHandle); i++)
{
Int32 childRowHandle = currentView.GetChildRowHandle(rowHandle, i);
if (currentView.IsGroupRow(childRowHandle))
SelectGroup(currentView, childRowHandle, select);
else
SelectRow(currentView, childRowHandle, select, false);
}
Invalidate(currentView);
}
public void SelectRow(GridView currentView, Int32 rowHandle, bool select)
{
SelectRow(currentView, rowHandle, select, true);
}
public void InvertRowSelection(GridView currentView, Int32 rowHandle)
{
if (currentView.IsDataRow(rowHandle))
SelectRow(currentView, rowHandle, !IsRowSelected(currentView, rowHandle));
if (currentView.IsGroupRow(rowHandle))
SelectGroup(currentView, rowHandle, !IsGroupRowSelected(currentView, rowHandle));
}
public bool IsGroupRowSelected(GridView currentView, Int32 rowHandle)
{
for (Int32 i = 0; i < currentView.GetChildRowCount(rowHandle); i++)
{
Int32 row = currentView.GetChildRowHandle(rowHandle, i);
if (currentView.IsGroupRow(row))
{
if (!IsGroupRowSelected(currentView, row)) return false;
}
else
if (!IsRowSelected(currentView, row)) return false;
}
return true;
}
public bool IsRowSelected(GridView currentView, Int32 rowHandle)
{
if (currentView.IsGroupRow(rowHandle))
return IsGroupRowSelected(currentView, rowHandle);
object row = currentView.GetRow(rowHandle);
return GetSelectedIndex(row) != -1;
}
#endregion
#region Attach|Detach
protected virtual void Attach(RepositoryItemGridLookUpEdit rep)
{
if (rep == null) return;
selection.Clear();
_currentRepository = rep;
edit = _currentRepository.View.GridControl.RepositoryItems.Add("CheckEdit") as RepositoryItemCheckEdit;
GridColumn column = _currentRepository.View.Columns.Add();
column.OptionsColumn.AllowSort = DevExpress.Utils.DefaultBoolean.False;
column.Visible = true;
column.VisibleIndex = 0;
column.FieldName = checkColumnFieldName;
column.Caption = "Mark";
column.OptionsColumn.ShowCaption = false;
column.OptionsColumn.AllowEdit = false;
column.OptionsColumn.AllowSize = false;
column.UnboundType = DevExpress.Data.UnboundColumnType.Boolean;
column.Width = GetCheckBoxWidth();
column.ColumnEdit = edit;
_currentRepository.View.Click += new EventHandler(View_Click);
_currentRepository.View.CustomDrawColumnHeader += new ColumnHeaderCustomDrawEventHandler(View_CustomDrawColumnHeader);
_currentRepository.View.CustomDrawGroupRow += new RowObjectCustomDrawEventHandler(View_CustomDrawGroupRow);
_currentRepository.View.CustomUnboundColumnData += new CustomColumnDataEventHandler(view_CustomUnboundColumnData);
_currentRepository.View.KeyDown += new KeyEventHandler(view_KeyDown);
}
protected virtual void Detach()
{
if (_currentRepository == null) return;
if (edit != null)
{
_currentRepository.View.GridControl.RepositoryItems.Remove(edit);
edit.Dispose();
}
_currentRepository.View.Click -= new EventHandler(View_Click);
_currentRepository.View.CustomDrawColumnHeader -= new ColumnHeaderCustomDrawEventHandler(View_CustomDrawColumnHeader);
_currentRepository.View.CustomDrawGroupRow -= new RowObjectCustomDrawEventHandler(View_CustomDrawGroupRow);
_currentRepository.View.CustomUnboundColumnData -= new CustomColumnDataEventHandler(view_CustomUnboundColumnData);
_currentRepository.View.KeyDown -= new KeyEventHandler(view_KeyDown);
_currentRepository = null;
}
void Invalidate(GridView currentView)
{
currentView.BeginUpdate();
currentView.EndUpdate();
}
void SelectRow(GridView currentView, Int32 rowHandle, bool select, bool invalidate)
{
if (IsRowSelected(currentView, rowHandle) == select) return;
object row = currentView.GetRow(rowHandle);
if (select)
selection.Add(row);
else
selection.Remove(row);
if (invalidate)
Invalidate(currentView);
OnSelectionChanged();
}
void view_CustomUnboundColumnData(object sender, CustomColumnDataEventArgs e)
{
GridView currentView = sender as GridView;
if (e.Column != null && e.Column.FieldName == checkColumnFieldName)
{
if (e.IsGetData)
e.Value = IsRowSelected(currentView, currentView.GetRowHandle(e.ListSourceRowIndex));
else
SelectRow(currentView, currentView.GetRowHandle(e.ListSourceRowIndex), (bool)e.Value);
}
}
void view_KeyDown(object sender, KeyEventArgs e)
{
GridView currentView = sender as GridView;
if (currentView.FocusedColumn.FieldName != checkColumnFieldName || e.KeyCode != Keys.Space) return;
InvertRowSelection(currentView, currentView.FocusedRowHandle);
}
void View_Click(object sender, EventArgs e)
{
GridHitInfo info;
GridView currentView = (sender as GridView);
Point pt = currentView.GridControl.PointToClient(Control.MousePosition);
info = currentView.CalcHitInfo(pt);
if (info.Column != null && info.Column.FieldName == checkColumnFieldName)
{
if (info.InColumn)
{
if (SelectedCount == currentView.DataRowCount)
ClearSelection(currentView);
else
SelectAll(currentView);
}
if (info.InRowCell)
InvertRowSelection(currentView, info.RowHandle);
}
if (info.InRow && currentView.IsGroupRow(info.RowHandle) && info.HitTest != GridHitTest.RowGroupButton)
InvertRowSelection(currentView, info.RowHandle);
}
void View_CustomDrawColumnHeader(object sender, ColumnHeaderCustomDrawEventArgs e)
{
if (e.Column != null && e.Column.FieldName == checkColumnFieldName)
{
e.Info.InnerElements.Clear();
e.Painter.DrawObject(e.Info);
DrawCheckBox(e.Graphics, e.Bounds, SelectedCount == (sender as GridView).DataRowCount);
e.Handled = true;
}
}
void View_CustomDrawGroupRow(object sender, RowObjectCustomDrawEventArgs e)
{
DevExpress.XtraGrid.Views.Grid.ViewInfo.GridGroupRowInfo info;
info = e.Info as DevExpress.XtraGrid.Views.Grid.ViewInfo.GridGroupRowInfo;
info.GroupText = " " + info.GroupText.TrimStart();
e.Info.Paint.FillRectangle(e.Graphics, e.Appearance.GetBackBrush(e.Cache), e.Bounds);
e.Painter.DrawObject(e.Info);
Rectangle r = info.ButtonBounds;
r.Offset(r.Width + CheckboxIndent * 2 - 1, 0);
DrawCheckBox(e.Graphics, r, IsGroupRowSelected((sender as GridView), e.RowHandle));
e.Handled = true;
}
#endregion
#region CheckBox
protected Int32 GetCheckBoxWidth()
{
DevExpress.XtraEditors.ViewInfo.CheckEditViewInfo info = edit.CreateViewInfo() as DevExpress.XtraEditors.ViewInfo.CheckEditViewInfo;
Int32 width = 0;
GraphicsInfo.Default.AddGraphics(null);
try
{
width = info.CalcBestFit(GraphicsInfo.Default.Graphics).Width;
}
finally
{
GraphicsInfo.Default.ReleaseGraphics();
}
return width + CheckboxIndent * 2;
}
protected void DrawCheckBox(Graphics g, Rectangle r, bool Checked)
{
DevExpress.XtraEditors.ViewInfo.CheckEditViewInfo info;
DevExpress.XtraEditors.Drawing.CheckEditPainter painter;
DevExpress.XtraEditors.Drawing.ControlGraphicsInfoArgs args;
info = edit.CreateViewInfo() as DevExpress.XtraEditors.ViewInfo.CheckEditViewInfo;
painter = edit.CreatePainter() as DevExpress.XtraEditors.Drawing.CheckEditPainter;
info.EditValue = Checked;
info.Bounds = r;
info.CalcViewInfo(g);
args = new DevExpress.XtraEditors.Drawing.ControlGraphicsInfoArgs(info, new DevExpress.Utils.Drawing.GraphicsCache(g), r);
painter.Draw(args);
args.Cache.Dispose();
}
#endregion
}
2, 按如下方式使用
public FormMain()
{
InitializeComponent();
gridLookUpEdit1.Properties.DataSource = dtDepartment; //赋值一个DataTable
gridLookUpEdit1.Properties.ValueMember = "Id";
gridLookUpEdit1.Properties.DisplayMember = "Name";
gridLookUpEdit1.Properties.View.OptionsSelection.MultiSelect = true;
gridLookUpEdit1.CustomDisplayText += new DevExpress.XtraEditors.Controls.CustomDisplayTextEventHandler(gridLookUpDevice_CustomDisplayText);
GridCheckMarksSelection gridCheckMarks;
gridCheckMarks = new GridCheckMarksSelection(gridLookUpEdit1.Properties);
gridCheckMarks.SelectionChanged += new GridCheckMarksSelection.SelectionChangedEventHandler(gridCheckMarksDevice_SelectionChanged);
gridLookUpEdit1.Properties.Tag = gridCheckMarks;
}
private void gridCheckMarksDevice_SelectionChanged(object sender, EventArgs e)
{
if (ActiveControl is GridLookUpEdit)
{
StringBuilder sb = new StringBuilder();
foreach (DataRowView rv in (sender as GridCheckMarksSelection).Selection)
{
if (sb.ToString().Length > 0) { sb.Append(", "); }
sb.Append(rv["Name"].ToString());
}
(ActiveControl as GridLookUpEdit).Text = sb.ToString();
}
}
// 选中时更新显示的文本1
private void gridLookUpDevice_CustomDisplayText(object sender, DevExpress.XtraEditors.Controls.CustomDisplayTextEventArgs e)
{
StringBuilder sb = new StringBuilder();
GridCheckMarksSelection gridCheckMark = sender is GridLookUpEdit ? (sender as GridLookUpEdit).Properties.Tag as GridCheckMarksSelection : (sender as RepositoryItemGridLookUpEdit).Tag as GridCheckMarksSelection;
if (gridCheckMark == null) return;
foreach (DataRowView rv in gridCheckMark.Selection)
{
if (sb.ToString().Length > 0) { sb.Append(", "); }
sb.Append(rv["Name"].ToString());
}
e.DisplayText = sb.ToString();
m_sender = sender;
}
// 选中时更新显示的文本1
private List<String> SelectAllDeviceCode(object sender, DevExpress.XtraEditors.Controls.CustomDisplayTextEventArgs e)
{
List<String> strDeviceCodeList = new List<String>();
GridCheckMarksSelection gridCheckMark = sender is GridLookUpEdit ? (sender as GridLookUpEdit).Properties.Tag as GridCheckMarksSelection : (sender as RepositoryItemGridLookUpEdit).Tag as GridCheckMarksSelection;
if (gridCheckMark == null) return null;
foreach (DataRowView rv in gridCheckMark.Selection)
{
String deviceCode = rv["Code"].ToString();
strDeviceCodeList.Add(deviceCode);
}
return strDeviceCodeList;
}
object m_sender;
//获取选中的值
public DataTable GetSelectValues()
{
if (null == dtDepartment)
{
return null;
}
DataTable dt = dtDepartment.Clone(); //复制表结构
if (m_sender != null)
{
GridCheckMarksSelection gridCheckMark = m_sender is GridLookUpEdit ? (m_sender as GridLookUpEdit).Properties.Tag as GridCheckMarksSelection : (m_sender as RepositoryItemGridLookUpEdit).Tag as GridCheckMarksSelection;
if (gridCheckMark != null)
{
foreach (DataRowView rowView in gridCheckMark.Selection)
{
dt.Rows.Add( rowView.Row.ItemArray);
}
}
}
return dt;
}
private void button1_Click(object sender, EventArgs e)
{
GetSelectValues();
}
自定义组件
按上面那样使用太复杂了, 我们把这个组件封装一下方便使用
效果图:
代码:
// 多选下拉框, 数据源只支持DataTable , 默认字段Id,Name
public partial class MkSelectMulti : UserControl
{
public string Label
{
get { return labelControl1.Text; }
set { labelControl1.Text = value; }
}
public string ValueMember
{
get { return gridLookUpEdit1.Properties.ValueMember; }
set { gridLookUpEdit1.Properties.ValueMember = value; }
}
public string DisplayMember
{
get { return gridLookUpEdit1.Properties.DisplayMember; }
set { gridLookUpEdit1.Properties.DisplayMember = value; }
}
public DataTable DataSource
{
get { return (DataTable)gridLookUpEdit1.Properties.DataSource; }
set
{
if (null == value)
{
return;
}
gridLookUpEdit1.Properties.DataSource = value;
gridLookUpEdit1.Properties.ValueMember = string.IsNullOrEmpty(ValueMember) ? "Id": ValueMember;
gridLookUpEdit1.Properties.DisplayMember = string.IsNullOrEmpty(DisplayMember) ? "Name" : DisplayMember;
gridLookUpEdit1.Properties.View.OptionsSelection.MultiSelect = true;
GridCheckMarksSelection gridCheckMarks = new GridCheckMarksSelection(gridLookUpEdit1.Properties);
gridCheckMarks.SelectionChanged += new GridCheckMarksSelection.SelectionChangedEventHandler(gridCheckMarks_SelectionChanged);
gridLookUpEdit1.Properties.Tag = gridCheckMarks;
gridLookUpEdit1.CustomDisplayText += new DevExpress.XtraEditors.Controls.CustomDisplayTextEventHandler(gridLookUpDevice_CustomDisplayText);
}
}
public DataTable Values
{
get
{
if (null == DataSource)
{
return null;
}
DataTable dt = DataSource.Clone(); //复制表结构
if (m_sender != null)
{
GridCheckMarksSelection gridCheckMark = m_sender is GridLookUpEdit ? (m_sender as GridLookUpEdit).Properties.Tag as GridCheckMarksSelection : (m_sender as RepositoryItemGridLookUpEdit).Tag as GridCheckMarksSelection;
if (gridCheckMark != null)
{
foreach (DataRowView rowView in gridCheckMark.Selection)
{
dt.Rows.Add(rowView.Row.ItemArray);
}
}
}
return dt;
}
}
private object m_sender;
public MkSelectMulti()
{
InitializeComponent();
//gridLookUpEdit 实现列过滤
gridLookUpEdit1.Properties.View.OptionsView.ShowAutoFilterRow = true;
}
// 选中时更新显示的文本1
private void gridCheckMarks_SelectionChanged(object sender, EventArgs e)
{
if (ActiveControl is GridLookUpEdit)
{
StringBuilder sb = new StringBuilder();
foreach (DataRowView rv in (sender as GridCheckMarksSelection).Selection)
{
if (sb.ToString().Length > 0) { sb.Append(", "); }
sb.Append(rv[DisplayMember].ToString());
}
(ActiveControl as GridLookUpEdit).Text = sb.ToString();
}
}
// 选中时更新显示的文本2
private void gridLookUpDevice_CustomDisplayText(object sender, DevExpress.XtraEditors.Controls.CustomDisplayTextEventArgs e)
{
StringBuilder sb = new StringBuilder();
GridCheckMarksSelection gridCheckMark = sender is GridLookUpEdit ? (sender as GridLookUpEdit).Properties.Tag as GridCheckMarksSelection : (sender as RepositoryItemGridLookUpEdit).Tag as GridCheckMarksSelection;
if (gridCheckMark == null) return;
foreach (DataRowView rv in gridCheckMark.Selection)
{
if (sb.ToString().Length > 0) { sb.Append(", "); }
sb.Append(rv[DisplayMember].ToString());
}
e.DisplayText = sb.ToString();
m_sender = sender;
}
}