Option.jpg
namespace DataContol
{
    
using System;
    
using System.Drawing;
    
using System.Collections;
    
using System.Windows.Forms;
    
using System.Windows.Forms.Design;
    
using System.Drawing.Design;
    
using System.ComponentModel;

    
internal class AttributesListBox : CheckedListBox 
    
{
        
int lockUpdate = 0;//绘图位置
        public AttributesListBox() 
        
{
            
//将指定的样式位置设置为指定值
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
        }

        
public void ListBoxBeginUpdate() 
        
{
            
// 当向 System.Windows.Forms.ListBox 中一次添加一个项时,通过防止该控件绘图来维护性能,直到调用 
            BeginUpdate();
            lockUpdate
++;
        }

        
public void ListBoxEndUpdate() 
        
{
            
//在 System.Windows.Forms.ListBox.BeginUpdate 方法挂起绘制后,该方法恢复绘制 System.Windows.Forms.ListBox 控件。  
            EndUpdate();
            
if(--lockUpdate == 0)
                Invalidate();
//使控件的指定区域无效(将其添加到控件的更新区域,下次绘制操作时将重新绘制更新区域),并向控件发送绘制消息。还可以使分配给该控件的子控件无效。
        }

        
//重绘ListBox控件
        protected override void OnPaint(PaintEventArgs e) 
        
{
            
if(lockUpdate != 0return;
            
base.OnPaint(e);
        }

    }


    
/// <summary>
    
/// ListBox下拉复选项承载窗体
    
/// </summary>

    internal class AttributesEditorForm : Form 
    
{
        
private AttributesEditor mainEditor;
        
private AttributesListBox listBox;
        
private object editValue, originalValue;
        
int lockCheckUpdate;
        
public AttributesEditorForm(AttributesEditor editor) 
        
{
            lockCheckUpdate 
= 0;
            mainEditor 
= editor;
            
this.StartPosition = FormStartPosition.WindowsDefaultBounds;
            MaximizeBox 
= false;
            MinimizeBox 
= false;
            FormBorderStyle 
= System.Windows.Forms.FormBorderStyle.None;
            TopLevel 
= false;
            ShowInTaskbar 
= false;
            TopMost 
= true;
            
this.Font = Control.DefaultFont;
            listBox 
= new AttributesListBox();
            listBox.Font 
= Control.DefaultFont;
            listBox.BorderStyle 
= System.Windows.Forms.BorderStyle.None;
            listBox.Dock 
= DockStyle.Fill;
            listBox.ItemCheck 
+= new ItemCheckEventHandler(listBox_ItemCheckEventHandler);
            
this.ClientSize = new Size(0,listBox.ItemHeight * 7);
            Controls.Add(listBox);
        }

        
protected override bool ProcessDialogKey(Keys keyData) 
        
{
            
if(keyData == Keys.Enter) 
            
{
                mainEditor.edSvc.CloseDropDown();
                
return true;
            }

            
if(keyData == Keys.Escape) 
            
{
                editValue 
= originalValue;
                mainEditor.edSvc.CloseDropDown();
                
return true;
            }

            
return base.ProcessDialogKey(keyData);
        }

        
protected void listBox_ItemCheckEventHandler(object sender, ItemCheckEventArgs e) 
        
{
            
if(lockCheckUpdate != 0return;
            BeginUpdate(); 
            
try 
            
{
                
string optionName = listBox.Items[e.Index].ToString();
                
if(e.NewValue == CheckState.Checked) 
                    EnableOption(optionName);
                
else
                    DisableOption(optionName);
                UpdateListBox();
            }

            
finally 
            
{
                EndUpdate();
            }

        }

        
void BeginUpdate() 
        
{
            lockCheckUpdate
++;
        }

        
void EndUpdate() 
        
{
            lockCheckUpdate 
--;
        }

        
void SelectAll() 
        
{
            
foreach(string optionName in listBox.Items) 
            
{
                
if(optionName != noneOption) EnableOption(optionName);
            }

        }

        
void ClearAll() 
        
{
            
foreach(string optionName in listBox.Items) 
            
{
                
if(optionName != noneOption) DisableOption(optionName);
            }

        }

        
void UpdateListBox() 
        
{
            listBox.ListBoxBeginUpdate();
            
try 
            
{
                
for(int n = 0; n < listBox.Items.Count; n++
                
{
                    
string optionName = listBox.Items[n].ToString();
                    listBox.SetItemChecked(n, IsOptionEnabled(optionName));
                }

            }

            
finally 
            
{
                listBox.ListBoxEndUpdate();
            }

        }

        
protected int GetOptionValue(string optionName) 
        
{
            Type t 
= EditValue.GetType();
            
return (int)t.GetField(optionName).GetValue(EditValue);
        }

        
protected void ConvertFromInt(int value) 
        
{
            Type t 
= EditValue.GetType();
            editValue 
= Activator.CreateInstance(t);
            t.GetFields()[
0].SetValue(editValue, value);
        }

        
protected void DisableOption(string optionName) 
        
{
            
if(optionName == noneOption) 
            
{
                SelectAll();
                
return;
            }

            ConvertFromInt((
int)editValue & (~GetOptionValue(optionName)));
        }

        
protected void EnableOption(string optionName) 
        
{
            
if(optionName == noneOption) 
            
{
                ClearAll();
                
return;
            }

            ConvertFromInt((
int)editValue | GetOptionValue(optionName));
        }

        
protected bool IsOptionEnabled(string optionName) 
        
{
            
int opt = (int)editValue;
            
if(optionName == noneOption) return opt == GetOptionValue(optionName);
            
return (opt & GetOptionValue(optionName)) == GetOptionValue(optionName);
        }

        
public object EditValue 
        
{
            
get return editValue; }
            
set 
            
{
                
if(editValue == value) return;
                originalValue 
= editValue = value;
                listBox.Items.Clear();
                ArrayList list 
= GetFields(editValue.GetType());
                BeginUpdate();
                
try 
                
{
                    
foreach(System.Reflection.FieldInfo fi in list) 
                    
{
                        listBox.Items.Add(fi.Name, IsOptionEnabled(fi.Name) 
? CheckState.Checked : CheckState.Unchecked);
                    }

                }

                
finally 
                
{
                    EndUpdate();
                }

                
int maxItems = Math.Min(listBox.Items.Count, 15);
                
this.ClientSize = new Size(this.Size.Width,listBox.ItemHeight * maxItems);
            }

        }

        
protected ArrayList GetFields(Type t) 
        
{
            ArrayList list 
= new ArrayList();
            System.Reflection.FieldInfo[] fields 
= t.GetFields();
            
foreach(System.Reflection.FieldInfo field in fields) 
            
{
                
if(field.IsSpecialName) continue;
                list.Add(field);
            }

            list.Sort(
new FieldsComparer());
            
return list;
        }

        
const string noneOption = "None";
        
class FieldsComparer : IComparer 
        
{
            
int IComparer.Compare(object x, object y) 
            
{
                System.Reflection.FieldInfo fi1 
= x as System.Reflection.FieldInfo;
                System.Reflection.FieldInfo fi2 
= y as System.Reflection.FieldInfo;
                
if(fi1 == null || fi2 == nullreturn Comparer.Default.Compare(x, y);
                
if(fi1 == fi2) return 0;
                
if(fi1.Name == noneOption) return -1;
                
if(fi2.Name == noneOption) return 1;
                
return Comparer.Default.Compare(fi1.Name, fi2.Name);
            }

        }

    }


    
/// <summary>
    
/// 下拉列表复选属性组件,本类继承UITypeEditor以提供复选框设计期支持
    
/// </summary>

    public class AttributesEditor : UITypeEditor
    
{
        
internal IWindowsFormsEditorService edSvc = null;
        
public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value) 
        
{
            
if(context == null || context.Instance == null || provider == null)
                
return value;
            edSvc 
= (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
            
if(edSvc == nullreturn value;
            AttributesEditorForm form 
= new AttributesEditorForm(this);
            form.EditValue 
= value;
            edSvc.DropDownControl(form);
            value 
= form.EditValue;
            form.Dispose();
            edSvc 
= null;
            
return value;
        }

        
public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) 
        
{
            
if(context != null && context.Instance != null)
                
return UITypeEditorEditStyle.DropDown;
            
return base.GetEditStyle(context);
        }

    }

}

应用:
        private StyleOptions options;
        [Category(
"关联属性")]
        [Description(
"设置关联的控件."), Editor(typeof(AttributesEditor), typeof(System.Drawing.Design.UITypeEditor))]
        
public StyleOptions RationOption 
        
{
            
get return options; }
            
set 
            
{
                    options 
= value;
            }

        }

    [Flags]
    
public enum StyleOptions 
    
{
        None 
= 0,
        TextBoxEx 
= 1,
        ComboListEdit 
= 2
    }

posted on 2005-10-26 15:08  蚂蚁  阅读(468)  评论(0)    收藏  举报