using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Data;
using System.Drawing;
using System.Drawing.Design;
using System.Reflection;
using System.Text;
using System.Windows.Forms;
using System.Windows.Forms.Design;
namespace WindowsFormsApplication1
{
public class Form1
: Form
{
public Form1
()
{
var propertyGrid1
= new System.Windows.Forms.PropertyGrid();
this.SuspendLayout();
//
// propertyGrid1
//
propertyGrid1
.Location = new System.Drawing.Point(54,
12);
propertyGrid1
.Name = "propertyGrid1";
propertyGrid1
.Size = new System.Drawing.Size(265,
243);
propertyGrid1
.TabIndex = 0;
propertyGrid1
.SelectedObject = new TestClass
();
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F
);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(539,
310);
this.Controls.Add(propertyGrid1
);
this.ResumeLayout(false);
}
}
public class TestClass
{
private int _value1
;
private string _value2
;
[Editor
(typeof(TableEditor
),
typeof(System.Drawing.Design.UITypeEditor))]
[TableEditorSettings
("ID1",
"TEXT",
"GetDataTable",
"")]
public int Value1
{
get
{ return _value1
; }
set
{ _value1
= value
; }
}
[Editor
(typeof(TableEditor
),
typeof(System.Drawing.Design.UITypeEditor))]
[TableEditorSettings
("ID2",
"TEXT",
"GetDataTable",
"")]
public string Value2
{
get
{ return _value2
; }
set
{ _value2
= value
; }
}
private static DataTable _dataTable
= null;
public static DataTable GetDataTable
()
{
if (_dataTable
== null) {
_dataTable
= new DataTable
("test");
_dataTable
.Columns.Add("ID1",
typeof(int));
_dataTable
.Columns.Add("ID2",
typeof(string));
_dataTable
.Columns.Add("TEXT",
typeof(string));
_dataTable
.Rows.Add(1,
"one",
"first");
_dataTable
.Rows.Add(2,
"two",
"second");
_dataTable
.Rows.Add(3,
"three",
"third");
}
return _dataTable
;
}
}
public delegate DataTable GetDataTableDelegate
();
public delegate DataGridView GetDataGridViewDelegate
();
public class TableEditorSettingsAttribute
: Attribute
{
private string _valueColumnName
;
private string _displayColumnName
;
private string _getDataTable
;
private string _getDataGrid
;
// kolona koja nosi vrednost
public string ValueColumnName
{
get
{ return _valueColumnName
; }
}
// koona koja se moze koristiti za opis vrednosti (na primer preko TypeConvertera, za sada se ne koristi)
public string DisplayColumnName
{
get
{ return _displayColumnName
; }
}
// naziv metode koja ce vratiti DataTable
public string GetDataTable
{
get
{ return _getDataTable
; }
}
// naziv metode koja ce vratiti DataGridView (ako nije navedeno bice kreiran default-ni DataGridView)
public string GetDataGrid
{
get
{ return _getDataGrid
; }
}
public TableEditorSettingsAttribute
(string valueColumnName,
string displayColumnName,
string getDataTable,
string getDataGrid
)
{
_valueColumnName
= valueColumnName
;
_displayColumnName
= displayColumnName
;
_getDataTable
= getDataTable
;
_getDataGrid
= getDataGrid
;
}
public static TableEditorSettingsAttribute GetTableEditorSettingsAttribute
(PropertyDescriptor pd
)
{
if(pd
!= null) {
foreach(Attribute attribute
in pd
.Attributes) {
if(attribute
.GetType() == typeof(TableEditorSettingsAttribute
)) {
return attribute
as TableEditorSettingsAttribute
;
}
}
}
return null;
}
}
public class TableEditor
: UITypeEditor
{
public override object EditValue
(ITypeDescriptorContext context, IServiceProvider provider,
object value
)
{
if (context
!= null && context
.Instance != null && provider
!= null) {
IWindowsFormsEditorService edSvc
= (IWindowsFormsEditorService
)provider
.GetService(typeof(IWindowsFormsEditorService
));
if (edSvc
!= null) {
var settings
= TableEditorSettingsAttribute
.GetTableEditorSettingsAttribute(context
.PropertyDescriptor);
TableEditorControl tableEditorControl
= new TableEditorControl
(edSvc, context
.PropertyDescriptor.ComponentType, value, settings
);
if (tableEditorControl
!= null && tableEditorControl
.DropDownControl != null) {
edSvc
.DropDownControl(tableEditorControl
.DropDownControl);
object newValue
= tableEditorControl
.Value;
tableEditorControl
.Dispose();
return newValue
;
}
}
}
return value
;
}
public override UITypeEditorEditStyle GetEditStyle
(ITypeDescriptorContext context
)
{
return UITypeEditorEditStyle
.DropDown;
}
private class TableEditorControl
: IDisposable
{
public void Dispose
()
{
if (grid
!= null) grid
.Dispose();
if (bindingSource
!= null) bindingSource
.Dispose();
if (dataTable
!= null) dataTable
.Dispose();
grid
= null;
bindingSource
= null;
dataTable
= null;
}
private IWindowsFormsEditorService edSvc
= null;
private DataGridView grid
= null;
private BindingSource bindingSource
= null;
private DataTable dataTable
= null;
private object _value
;
private TableEditorSettingsAttribute settings
;
public object Value
{
get
{
if (bindingSource
!= null && bindingSource
.Current is DataRowView
&& settings
!= null && !string.IsNullOrEmpty(settings
.ValueColumnName)) {
return ((DataRowView
)bindingSource
.Current)[settings
.ValueColumnName];
}
return null;
}
}
public Control DropDownControl
{
get
{ return grid
; }
}
private static MethodInfo GetMethod
(Type type,
string methodName
)
{
if (type
!= null && !string.IsNullOrEmpty(methodName
)) {
return type
.GetMethod(methodName, BindingFlags
.Static | BindingFlags
.Public | BindingFlags
.NonPublic);
}
return null;
}
public TableEditorControl
(IWindowsFormsEditorService edSvc, Type classType,
object value, TableEditorSettingsAttribute settings
)
{
this.edSvc = edSvc
;
this._value
= value
;
this.settings = settings
;
if (this.edSvc != null && classType
!= null && settings
!= null) {
MethodInfo getDataTable
= GetMethod
(classType, settings
.GetDataTable);
if (getDataTable
!= null) {
dataTable
= getDataTable
.Invoke(null,
new object[] { }) as DataTable
;
}
if (dataTable
== null) {
dataTable
= new DataTable
();
}
MethodInfo getDataGrid
= GetMethod
(classType, settings
.GetDataGrid);
if (getDataGrid
!= null) {
grid
= getDataGrid
.Invoke(null,
new object[] { }) as DataGridView
;
}
if (grid
== null) {
grid
= new DataGridView
();
grid
.SelectionMode = DataGridViewSelectionMode
.FullRowSelect;
grid
.ReadOnly = true;
}
bindingSource
= new BindingSource
();
bindingSource
.DataSource = dataTable
;
grid
.DataSource = bindingSource
;
grid
.VisibleChanged += new EventHandler
(grid_VisibleChanged
);
}
}
private bool handlerSet
= false;
void grid_VisibleChanged
(object sender, EventArgs e
)
{
if (grid
!= null && grid
.Parent != null && grid
.Parent.Visible) {
grid
.Parent.Size = new Size
(400,
200);
// zatvaranje dropdown kontrole se obicno izvrsi kada korisnik odabere vrednost
// u ovom slucaju kada se na bindingSource promeni selekcija
// iz nekog razloga ako handler postavimo u konstruktoru desava se da pri svakom drugom otvaranju kontrole
// se automatski izvrsi ovaj handler i kontrola se odmah zatvori
// zato ovaj handler postavljamo tek kada se kontrola prikaze
// takodje tada i postavljamo poziciju (ne fukncionise u konstruktoru)
if (!handlerSet
) {
if (settings
!= null && !string.IsNullOrEmpty(settings
.ValueColumnName)) {
bindingSource
.Position = bindingSource
.Find(settings
.ValueColumnName, _value
);
}
bindingSource
.CurrentChanged += new EventHandler
(bindingSource_CurrentChanged
);
handlerSet
= true;
}
}
}
void bindingSource_CurrentChanged
(object sender, EventArgs e
)
{
// ovde bi trebalo da direktno pozivamo CloseDropDown ali u slucaju DataGridView kontrole ovo izaziva Exception
// zato pozivamo preko BeginInvoke
if (grid
!= null) grid
.BeginInvoke(new MethodInvoker
(CloseDropDown
));
}
void CloseDropDown
()
{
if (edSvc
!= null) edSvc
.CloseDropDown();
}
}
}
}