关闭

自定义ListEditor

596人阅读 评论(0) 收藏 举报

一.关于ListEditor

       ListEditor是ListView的可视化体现。ListEditor拥有一个Control,该Control的作用是显示ListView的对象集合。ListEditor管理该Control,负责Control的创建,数据绑定和管理Control与ListView之间的交互。

      从现有View获取ListEditor及其Control:

      ListEditor     editor=((ListView)View).Editor;
      //若该ListEditor的control是GridControl,使用ListEditor.Control属性获取该Control
     GridControl gc=(GridControl)editor.Control;

     若要实现自定义的ListEditor,必须用ListEditorAttribute特性标记该自定义的类。

二.自定义ListEditor(该例来自于http://documentation.devexpress.com/#Xaf/CustomDocument2659 )

    我们准备为一个图片类型实现自定义ListEditor,在Solution.Module中声明该接口。

using System.Drawing;
interface IPictureItem {
Image Image { get; }
string Text { get; }
string ID { get; }
}

         然后在Solution.Module.Win中实现自定义的ListEditor类

 /*Typical implementation of the ListEditor class' descendants comprises the following steps:


1.Override the CreateControlsCore method. Create and configure an instance of the control that will represent a List View in a UI. Handle the control's events to call the following methods:
  - OnProcessSelectedItem
  - OnSelectionChanged
  - OnFocusedObjectChanging
  - OnFocusedObjectChanged
  - OnNewObjectAdding
  - OnNewObjectCanceled
  - OnNewObjectCreated
2.Override the AssignDataSourceToControl method. Assign the List Editor's data source to its control.
3.Override the Refresh method. Refresh data in the List Editor's control.
4.Override the RequiredProperties property. Return business class' property names that are used by the List Editor when displaying objects. These properties are treated as displayable if a List View's data source is derived from the XPBaseCollection.
5.Override the SelectionType property. Return the selection type supported by the List Editor's control.
6.Override the GetSelectedObjects method. Return a list of the selected objects.
7.Override the FocusedObject method. Get and set the control's focused object.
8.If the custom List Editor does not support server mode (CollectionSourceBase.IsServerMode), override the IsServerModeSupported property and set it to false. It is also recommended that you implement a custom generator updater to disable server mode for List Views visualized by the custom List Editor. For details, see the IsServerModeSupported property description.
9.Modify the constructor to instantiate the control that will represent the List Editor's pop-up menu. This control must implement the IDXPopupMenuHolder interface to support XAF architecture. Override the ContextMenuTemplate property to return the created instance of the control.
10.Mark the custom List Editor with the ListEditorAttribute.
 
 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DevExpress.ExpressApp.Editors;
using System.Windows.Forms;
using System.ComponentModel;
using DevExpress.ExpressApp.Utils;
using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Model;
using System.Collections;
using DevExpress.ExpressApp.Templates;
using DevExpress.ExpressApp.Win.Controls;
using DevExpress.Utils.Menu;
using System.Drawing;
using DevExpress.ExpressApp.SystemModule;
using ListEditorSolution.Module;




namespace ListEditorSolution.Module.Win
{
    /*自定义WinCustomListEditor需要继承ListEditor;若要为其实现上下文菜单,则需要实现
      IDXPopupMenuHolder接口,该接口暴露了如下成员,需要重写它们:
      CanShowPopupMenu
      SetMenuManager
      PopupSite
    */
    //该ListEditor属性表示为IPictureItem类型使用WinCustomListEditor
    [ListEditor(typeof(IPictureItem))]
    public class WinCustomListEditor : ListEditor, IDXPopupMenuHolder
    {
        //上下文菜单
        private ActionsDXPopupMenu popupMenu;
        //ListView is a Control.声明WinCustomListEditor的Control
        private System.Windows.Forms.ListView control; 
        private System.Windows.Forms.ImageList images;
        //ListEditor的数据集合
        private IList controlDataSource;
        public WinCustomListEditor(IModelListView info) : base(info)
        {
            //初始化上下文菜单
            popupMenu = new ActionsDXPopupMenu();
        }
        //实例化WinCustomListEditor的control,并配置该control
        protected override object CreateControlsCore()
        {
            control = new System.Windows.Forms.ListView();
            images = new System.Windows.Forms.ImageList();
            images.ImageSize = new System.Drawing.Size(104, 150);
            images.ColorDepth = ColorDepth.Depth32Bit;
            control.LargeImageList = images;
            control.HideSelection = false;
            //订阅选中,焦点等事件
            /*只要 ListViewItem 的 Selected 属性发生改变,SelectedIndices 集合就会更改。 
            属性更改可以编程方式发生,也可以在用户选择项或取消选择项时发生。 
            当用户选择某项(但没有按 Ctrl 选择多项)时,该控件首先取消选择以前选择的项。 
            在这种情况下,此事件会发生两次,一次是针对以前选择的每一项,一次是针对新选择的项。*/
            control.SelectedIndexChanged += new EventHandler(control_SelectedIndexChanged);
            //项状态无论是从选定变为非选定,还是从非选定变为选定,均发生 ItemSelectionChanged 事件
            control.ItemSelectionChanged +=
            new System.Windows.Forms.ListViewItemSelectionChangedEventHandler(
            control_ItemSelectionChanged);
            //订阅鼠标双击,按下Enter键事件
            control.MouseDoubleClick += new MouseEventHandler(control_MouseDoubleClick);
            control.KeyDown += new System.Windows.Forms.KeyEventHandler(control_KeyDown);
            Refresh();
            return control;
        }
        //绑定ListEditor的数据源到它的control,当数据源是IBindingList,订阅数据更改事件
        protected override void AssignDataSourceToControl(object oDataSource)
        {
            IList dataSource = (IList)oDataSource;
            if (controlDataSource != dataSource)
            {
                IBindingList oldBindable = controlDataSource as IBindingList;
                if (oldBindable != null)
                {
                    oldBindable.ListChanged -= new ListChangedEventHandler(dataSource_ListChanged);
                }
                controlDataSource = dataSource;
                //若数据集合实现了IBindingList,则订阅ListChanged事件
                IBindingList bindable = controlDataSource as IBindingList;
                if (bindable != null)
                {
                    bindable.ListChanged += new ListChangedEventHandler(dataSource_ListChanged);
                }
                Refresh();
            }
        }
        void dataSource_ListChanged(object sender, ListChangedEventArgs e)
        {
            Refresh();
        }
        public override void Refresh()
        {
            if (control == null)
                return;
            //保存FocusedObject
            object focused = FocusedObject;
            control.SelectedItems.Clear();
            try
            {
                /*将多个项添加到 ListView 的首选方法是使用 ListView.ListViewItemCollection(通过 
                ListView 的 Items 属性访问)的 AddRange 方法。这使您得以在一个操作中就可将一组项添
                加到列表中。然而,如果希望使用 ListView.ListViewItemCollection 类的 Add 方法以每
                次一个的方式添加项,则可以使用 BeginUpdate 方法防止控件在每次添加项时重新绘制 ListView。
                在完成将项添加到控件的任务后,请调用 EndUpdate 方法以使 ListView 能够重新绘制。这种添加
                项的方法可以防止将大量项添加到控件时发生闪烁的 ListView 绘制*/
                control.BeginUpdate();
                images.Images.Clear();
                control.Items.Clear();
                //得到IList类型的数据集合
                if (ListHelper.GetList(controlDataSource) != null)
                {
                    //Module.Win.Image下必须存在NoImage 图片作为默认图片
                    images.Images.Add(ImageLoader.Instance.GetImageInfo("NoImage").Image);
                    foreach (IPictureItem item in ListHelper.GetList(controlDataSource))
                    {
                        int imageIndex = 0;
                        if (item.Image != null)
                        {
                            images.Images.Add(item.Image);
                            imageIndex = images.Images.Count - 1;
                        }
                        //创建并初始化一个ListViewItem
                        System.Windows.Forms.ListViewItem lItem =
                        new System.Windows.Forms.ListViewItem(item.Text, imageIndex);
                        //附加图片,ListViewItem利用构造函数参数的imageIndex索引该图片对象
                        lItem.Tag = item;
                        //将该ListViewItem添加到ListView中
                        control.Items.Add(lItem);
                    }
                }
            }
            finally
            {
                control.EndUpdate();
            }
            //恢复FocusedObject
            FocusedObject = focused;
            if (FocusedObject == null && control.Items.Count > 1)
            {
                FocusedObject = control.Items[0].Tag;
            }
        }
        //接触数据绑定,销毁上下文菜单
        public override void Dispose()
        {
            controlDataSource = null;
            if (popupMenu != null)
            {
                popupMenu.Dispose();
                popupMenu = null;
            }
            base.Dispose();
        }


        void control_ItemSelectionChanged(object sender,System.Windows.Forms.ListViewItemSelectionChangedEventArgs e)
        {
            OnSelectionChanged();
        }
        void control_SelectedIndexChanged(object sender, EventArgs e)
        {
            OnSelectionChanged();
            OnFocusedObjectChanged();
        }
        public override SelectionType SelectionType
        {
            get { return SelectionType.Full; }
        }
        public override IList GetSelectedObjects()
        {
            if (control == null) return new object[0] { };
            object[] result = new object[control.SelectedItems.Count];
            for (int i = 0; i < control.SelectedItems.Count; i++)
            {
                result[i] = control.SelectedItems[i].Tag;
            }
            return result;
        }
        void control_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
                OnProcessSelectedItem();
        }
        void control_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                OnProcessSelectedItem();
            }
        }
        //根据已有的IPictureItem定位control中的ListViewItem
        private System.Windows.Forms.ListViewItem FindByTag(object tag)
        {
            IPictureItem itemToSearch = (IPictureItem)tag;
            if (control != null && itemToSearch != null)
            {
                foreach (System.Windows.Forms.ListViewItem item in control.Items)
                {
                    if (((IPictureItem)item.Tag).ID == itemToSearch.ID)
                        return item;
                }
            }
            return null;
        }
        public override object FocusedObject
        {
            get {
                return (control != null) && (control.FocusedItem != null) ?
                control.FocusedItem.Tag : null;
            }
            set
            {
                System.Windows.Forms.ListViewItem item = FindByTag(value);
                if (item != null)
                {
                    control.SelectedItems.Clear();
                    item.Focused = true;
                    item.Selected = true;
                }
            }
        }
        public override IContextMenuTemplate ContextMenuTemplate
        {
            get { return popupMenu; }
        }
        public bool CanShowPopupMenu(System.Drawing.Point position)
        {
            System.Drawing.Point clientPosition = control.PointToClient(position);
            return clientPosition != Point.Empty;
        }
        public void SetMenuManager(IDXMenuManager manager) { }
        //返回右键菜单所属的control
        public Control PopupSite
        {
            get { return control; }
        }
        public override void SaveModel() { }
    }
}

使用该ListEditor:
[DefaultClassOptions]
    public class Persons : BaseObject , IPictureItem
    {
        public Persons(Session session)
            : base(session)
        {
            // This constructor is used when an object is loaded from a persistent storage.
            // Do not place any code here or place it only when the IsLoading property is false:
            // if (!IsLoading){
            //    It is now OK to place your initialization code here.
            // }
            // or as an alternative, move your initialization code into the AfterConstruction method.
        }
        public override void AfterConstruction()
        {
            base.AfterConstruction();
            // Place here your initialization code.
        }


        public string Title
        {
            get { return GetPropertyValue<string>("Title"); }
            set { SetPropertyValue<string>("Title", value); }
        }
        [Size(SizeAttribute.Unlimited), ValueConverter(typeof(ImageValueConverter))]
        public Image Cover
        {
            get { return GetPropertyValue<Image>("Cover"); }
            set { SetPropertyValue<Image>("Cover", value); }
        }
        public String Director
        {
            get { return GetPropertyValue<String>("Director"); }
            set { SetPropertyValue<String>("Director", value); }
        }
        #region IPictureItem Members
        //这几个字段从IPictureItem继承而来,不是BaseObject的成员,不会在数据库生成字段
        Image IPictureItem.Image
        {
            get { return Cover; }
        }
        string IPictureItem.Text
        {
            get { return String.Format("{0} by {1}", Title, Director); }
        }
        string IPictureItem.ID
        {
            get { return Oid.ToString(); }
        }
        #endregion


    }


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:198662次
    • 积分:3145
    • 等级:
    • 排名:第11376名
    • 原创:106篇
    • 转载:40篇
    • 译文:5篇
    • 评论:36条
    文章分类
    最新评论