Devexpress Lookup 编辑器功能与常规 ComboBox 相同

Devexpress Lookup editor function as a regular ComboBox

我需要 Devexpress Lookup 编辑器功能作为一个常规的组合框,所以当用户点击网格中的单元格后,会出现另一个具有多列的网格。用户也可以添加新值,但新值无法保存在数据源中,但下次输入表单后该值不会消失。现在我在单元格中有简单的 RepositoryItemTextEdit 并且已经有值,所以在代码更改后值必须保持不变。

现在数据源之外的值在离开和进入表单后消失。来自数据源的值保留,但在单元格失去焦点后,单元格中的值显示 "Value is empty".

到目前为止我的代码(我使用 https://www.devexpress.com/Support/Center/Example/Details/E2297):

//////////////////////class MyObject
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Collections;

namespace APP
{
    public class MyObject
    {
        public MyObject()
        {}

        private object _Value;
        public object Value
        {
            get { return _Value; }
            set { _Value = value; }
        }
    }
}

//////////////class MyDataSourceWrapper
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Collections;

namespace APP
{
    class MyDataSourceWrapper : ITypedList, IList
    {
        private readonly string _DisplayMember;
        public readonly IList NestedList;
        public ITypedList NestedTypedList { get { return (ITypedList)NestedList; } }
        public MyDataSourceWrapper(ITypedList list, MyObject nullObject, string valueMember, string displayMember)
        {
            _ValueMember = valueMember;
            _DisplayMember = displayMember;
            _NullObject = nullObject;
            this.NestedList = (IList)list;
        }

        private MyObject _NullObject;
        private readonly string _ValueMember;
        public MyObject NullObject
        {
            get { return _NullObject; }
            set { _NullObject = value; }
        }

        class EmptyObjectPropertyDescriptor : PropertyDescriptor
        {
            private readonly string _DisplayMember;
            public readonly PropertyDescriptor NestedDescriptor;
            public readonly MyObject NullObject;
            private readonly string _ValueMember;
            public EmptyObjectPropertyDescriptor
                (PropertyDescriptor nestedDescriptor, MyObject nullObject, string valueMember, string displayMember)
                : base(nestedDescriptor.Name, (Attribute[])new ArrayList(nestedDescriptor.Attributes).ToArray(typeof(Attribute)))
            {
                _DisplayMember = displayMember;
                _ValueMember = valueMember;
                this.NestedDescriptor = nestedDescriptor;
                this.NullObject = nullObject;
            }
            public override bool CanResetValue(object component)
            {
                return false;
            }
            public override Type ComponentType
            {
                get { return typeof(object); }
            }
            public override object GetValue(object component)
            {
                if (component == NullObject)
                {
                    if (NestedDescriptor.Name == _ValueMember)
                        return NullObject.Value;
                    else if (NestedDescriptor.Name == _DisplayMember)
                        return NullObject.Value;
                    return null;
                }
                else
                    return NestedDescriptor.GetValue(component);
            }
            public override bool IsReadOnly
            {
                get { return true; }
            }
            public override Type PropertyType
            {
                get { return NestedDescriptor.PropertyType; }
            }
            public override void ResetValue(object component)
            {
                throw new NotSupportedException("The method or operation is not implemented.");
            }
            public override void SetValue(object component, object value)
            {
                throw new NotSupportedException("The method or operation is not implemented.");
            }
            public override bool ShouldSerializeValue(object component)
            {
                return true;
            }
        }
        public PropertyDescriptorCollection GetItemProperties(PropertyDescriptor[] listAccessors)
        {
            List<PropertyDescriptor> result = new List<PropertyDescriptor>();
            foreach (PropertyDescriptor pd in NestedTypedList.GetItemProperties(ExtractOriginalDescriptors(listAccessors)))
            {
                object nullVal = null;
                if (pd.PropertyType == typeof(string))
                    nullVal = "[empty]";
                result.Add(new EmptyObjectPropertyDescriptor(pd, NullObject, _ValueMember, _DisplayMember));
            }
            return new PropertyDescriptorCollection(result.ToArray());
        }
        public string GetListName(PropertyDescriptor[] listAccessors)
        {
            return NestedTypedList.GetListName(ExtractOriginalDescriptors(listAccessors));
        }

        protected static PropertyDescriptor[] ExtractOriginalDescriptors(PropertyDescriptor[] listAccessors)
        {
            if (listAccessors == null)
                return null;
            PropertyDescriptor[] convertedDescriptors = new PropertyDescriptor[listAccessors.Length];
            for (int i = 0; i < convertedDescriptors.Length; ++i)
            {
                PropertyDescriptor d = listAccessors[i];
                EmptyObjectPropertyDescriptor c = d as EmptyObjectPropertyDescriptor;
                if (c != null)
                    convertedDescriptors[i] = c.NestedDescriptor;
                else
                    convertedDescriptors[i] = d;
            }
            return convertedDescriptors;
        }
        public int Add(object value)
        {
            throw new NotSupportedException("The method or operation is not implemented.");
        }
        public void Clear()
        {
            throw new NotSupportedException("The method or operation is not implemented.");
        }
        public bool Contains(object value)
        {
            if (value == NullObject)
                return true;
            return NestedList.Contains(value);
        }
        public int IndexOf(object value)
        {
            if (value == NullObject)
                return 0;
            int nres = NestedList.IndexOf(value);
            if (nres < 0)
                return nres;
            return nres + 1;
        }
        public void Insert(int index, object value)
        {
            throw new NotSupportedException("The method or operation is not implemented.");
        }
        public bool IsFixedSize
        {
            get { return true; }
        }
        public bool IsReadOnly
        {
            get { return true; }
        }
        public void Remove(object value)
        {
            throw new NotSupportedException("The method or operation is not implemented.");
        }
        public void RemoveAt(int index)
        {
            throw new NotSupportedException("The method or operation is not implemented.");
        }
        public object this[int index]
        {
            get
            {
                if (index == 0)
                    return NullObject;
                else
                    return NestedList[index - 1];
            }
            set
            {
                throw new NotSupportedException("The method or operation is not implemented.");
            }
        }
        public void CopyTo(Array array, int index)
        {
            throw new NotSupportedException("The method or operation is not implemented.");
        }
        public int Count
        {
            get { return NestedList.Count + 1; }
        }
        public bool IsSynchronized
        {
            get { return false; }
        }
        public object SyncRoot
        {
            get { return NestedList.SyncRoot; }
        }
        public IEnumerator GetEnumerator()
        {
            throw new NotSupportedException("The method or operation is not implemented.");
        }
    }
}

//////////////////class MyGridLookupDataSourceHelper
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using DevExpress.XtraEditors;
using DevExpress.XtraGrid;
using System.Collections;

using DevExpress.XtraEditors.Repository;
using DevExpress.XtraGrid.Columns;
using DevExpress.XtraLayout;
using DevExpress.Utils;

namespace APP
{
    public class MyGridLookupDataSourceHelper
    {

        MyObject _MyObject = new MyObject();
        private MyDataSourceWrapper _DataSourceWrapper;
        GridLookUpEdit edit;
        bool popupOpened = false;
        public MyGridLookupDataSourceHelper(GridLookUpEdit edit, ITypedList dataSource, string displayMember, string valueMember)
        {
            this.edit = edit;
            _DataSourceWrapper = new MyDataSourceWrapper(dataSource, _MyObject, valueMember, displayMember);
            edit.Properties.DisplayMember = displayMember;
            edit.Properties.ValueMember = valueMember;
            edit.Properties.DataSource = _DataSourceWrapper;
            edit.Properties.View.CustomRowFilter += View_CustomRowFilter;
            edit.ProcessNewValue += edit_ProcessNewValue;
            edit.Properties.View.RefreshData();
            edit.Properties.QueryPopUp += new CancelEventHandler(Properties_QueryPopUp);
        }

        void Properties_QueryPopUp(object sender, CancelEventArgs e)
        {
            this.popupOpened = true;
            edit.Properties.View.DataController.DoRefresh();
        }

        public static void SetupGridLookUpEdit(GridLookUpEdit edit, ITypedList dataSource, string displayMember, string valueMember)
        {
            new MyGridLookupDataSourceHelper(edit, dataSource, displayMember, valueMember);
        }

        void View_CustomRowFilter(object sender, DevExpress.XtraGrid.Views.Base.RowFilterEventArgs e)
        {
            if (!popupOpened) return;
            if (_DataSourceWrapper[e.ListSourceRow] is MyObject)
            {
                e.Visible = false;
                e.Handled = true;
            }
        }

        void edit_ProcessNewValue(object sender, DevExpress.XtraEditors.Controls.ProcessNewValueEventArgs e)
        {
            _MyObject.Value = e.DisplayValue;
            this.popupOpened = false;
            edit.Properties.View.DataController.DoRefresh();
            e.Handled = true;
        }
    }
}

/////////////////////////code used in Main
   GridLookUpEdit glue = new GridLookUpEdit();
            glue.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.Standard;
            MyGridLookupDataSourceHelper.SetupGridLookUpEdit(glue, GetMaterialyDataView(), "Kod", "Kod");
            eePozycje.gvView.Columns[KolNazwa].ColumnEdit = glue.Properties;

您稍微修改了示例,您编写的代码将无法按预期运行。如果你想使用网格查找编辑网格列,那么你必须使用存储库项。你应该使用 RepositoryItemGridLookUpEdit 而不是 GridLookUpEdit.

之后您将能够在该列编辑器(RepositoryItemGridLookUpEdit)下查看单独的网格视图,然后您可以在网格查找编辑器下的网格列中看到另一个网格视图。

希望对您有所帮助。