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)下查看单独的网格视图,然后您可以在网格查找编辑器下的网格列中看到另一个网格视图。
希望对您有所帮助。
我需要 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)下查看单独的网格视图,然后您可以在网格查找编辑器下的网格列中看到另一个网格视图。
希望对您有所帮助。