简体   繁体   English

本机类型绑定源/如何使用字符串列表填充 DevExpress GridControl?

[英]Native type binding source / How to fill a DevExpress GridControl with a List of strings?

I normally have no problem with binding a DataSource to a GridControl.我通常将 DataSource 绑定到 GridControl 没有问题。 I usually so something like this:我通常是这样的:

myGrid.DataSource = myList // BindingList<ComplexObject>
colMyStrings.FieldName = "PropertyNameOfComplexObject";

and it works fine.它工作正常。 I can add and delete rows from the grid and they will get added to / deleted from the DataSource "myList".我可以从网格中添加和删除行,它们将被添加到数据源“myList”中/从数据源“myList”中删除。 So I basically always see what's in my List.所以我基本上总是看到我的列表中的内容。

But now I don't have a List<ComplexObject> , where the Generic Type has Properties, but I have a List filled with strings.但是现在我没有List<ComplexObject> ,其中通用类型具有属性,但我有一个填充字符串的 List 。

BindingList<string>

When I try to bind the List to my grid, it wont get that the strings themselves are what i want bound to the rows of my column and since string doesn't have any properties, there is nothing I can fill the columns .FieldName with.当我尝试将 List 绑定到我的网格时,它不会得到字符串本身就是我想要绑定到我的列的行的内容,并且由于字符串没有任何属性,因此我无法填充列.FieldName .

I know I could use a wrapper class to solve this problem, but I don't find this solution to be very nice.我知道我可以使用包装类来解决这个问题,但我觉得这个解决方案不是很好。

Is there a way to tell the column, that the data it should use is the Objects, in this case the strings, themselves?有没有办法告诉列,它应该使用的数据是对象,在这种情况下是字符串本身?

Update 1更新 1

This is something I tried.这是我尝试过的。 I thought if I could make my own GridControl and override the setter for the DataSource Property, I could make an internal Wrapper so that anyone who uses it wont need do so.我想如果我可以创建自己的 GridControl 并覆盖 DataSource 属性的 setter,我可以创建一个内部 Wrapper,这样任何使用它的人都不需要这样做。 This kind of works.这种作品。 I can add my DataSource BindingList<string> now, but for some reason I cant edit the values.我现在可以添加我的DataSource BindingList<string> ,但由于某种原因我无法编辑这些值。 I don't know why.我不知道为什么。

Here is the code:这是代码:

public partial class NativeTypeGrid : DevExpress.XtraGrid.GridControl
{
    public NativeTypeGrid()
    {
        InitializeComponent();
    }

    public override object DataSource
    {
        get
        {
            return base.DataSource;
        }
        set
        {
            if (value is IBindingList)
            {
                Type GenericType;
                IBindingList myList = (IBindingList) value;
                BindingList<Wrapper> wrappedList = new BindingList<Wrapper>();
                GenericType = myList.GetType().GetGenericArguments()[0];
                if(GenericType.IsPrimitive || GenericType == typeof(string))
                {
                    for(int i = 0; i < myList.Count; i++)
                    {
                        object obj = myList[i];
                        wrappedList.Add(new Wrapper(ref obj));
                    }

                    base.DataSource = wrappedList;
                }
                else
                {
                    base.DataSource = value;
                }
            }
            else
            {
                base.DataSource = value;
            }
        }
    }

    internal class Wrapper
    {
        private object _NativeTypeProperty;

        public Wrapper()
        {
            _NativeTypeProperty = "SomeValueForInitialization";
        }

        public Wrapper(ref object nativeType)
        {
            _NativeTypeProperty = nativeType;
        }

        public object NativeTypeProperty
        {
            get { return _NativeTypeProperty; }
            set { _NativeTypeProperty = value; }
        }
    }
}

Update 2更新 2

I already figured out why it won't get any by the user added objects.我已经弄清楚为什么用户添加的对象不会得到任何东西。 Of course it doesn't work since adding an Object to the DataSource uses the basic/empty constructor, which in turn means that my DataSource doesn't have that connection to the original List, which is the one I want the new objects to be in. I will work on this and update again.当然它不起作用,因为向数据源添加对象使用基本/空构造函数,这反过来意味着我的数据源没有与原始列表的连接,这是我希望新对象成为的那个in. 我会处理这个并再次更新。

Update 3更新 3

Couldn't think of any better solution, so I went with the initial approach and built a wrapper class for my strings.想不出更好的解决方案,所以我采用了最初的方法并为我的字符串构建了一个包装类。 Looks a little bit like this:看起来有点像这样:

class StringWrapper{
    public String MyString{ get; set;}
}

myGrid.DataSource = new BindingList<StringWrapper>();

I would still be happy to use another approach.我仍然很乐意使用另一种方法。

You can set the "Column" as Column.FieldName .您可以将"Column"设置为Column.FieldName
Here is example:这是示例:

var myList = new List<string>() { "String 0", "String 1", "String 2" };

myGrid.DataSource = myList;
colMyStrings.FieldName = "Column";

However you cannot add or modify the values in GridView , because DevExpress team does not implemented the properly usage of this case and you can only delete values.但是您不能在GridView添加或修改值,因为 DevExpress 团队没有实现这种情况的正确使用,您只能删除值。

But if you want to manipulate with your list by using GridControl , then you need to create list wrapper, not string wrapper.但是,如果您想使用GridControl操作您的列表,那么您需要创建列表包装器,而不是字符串包装器。 For this purpose you can implement IBindingList interface which is allowed as DataSource according to documentation .为此,您可以根据文档实现IBindingList接口,该接口允许作为DataSource
Here is example of simple list wrapper that implements IBindingList interface:这是实现IBindingList接口的简单列表包装器的示例:

public class ListWrapper<T> : IBindingList
{
    private IList<T> _wrappedList;

    public ListWrapper(IList<T> wrappedList)
    {
        _wrappedList = wrappedList;
    }

    #region IBindingList implementation
    #region Necessary members
    public object this[int index]
    {
        get { return new Wrapper(this, index); }//This wrapper have the Value property which is used as FieldName.
        set { Insert(index, value); }
    }

    public object AddNew()
    {
        _wrappedList.Add(default(T));

        return new Wrapper(this, Count - 1);
    }

    public void RemoveAt(int index)
    {
        _wrappedList.RemoveAt(index);
    }

    public int Count { get { return _wrappedList.Count; } }

    public IEnumerator GetEnumerator()
    {
        return new ListWrapperEnumerator(this);
    }

    private class Wrapper
    {
        private readonly ListWrapper<T> _listWrapper;
        private readonly int _index;

        public Wrapper(ListWrapper<T> listWrapper, int index)
        {
            _listWrapper = listWrapper;
            _index = index;
        }

        public T Value
        {
            get { return _listWrapper._wrappedList[_index]; }
            set { _listWrapper._wrappedList[_index] = value; }
        }
    }

    private class ListWrapperEnumerator : IEnumerator
    {
        private readonly ListWrapper<T> _listWrapper;
        private int _currentIndex;

        public ListWrapperEnumerator(ListWrapper<T> listWrapper)
        {
            _listWrapper = listWrapper;

            Reset();
        }

        public object Current
        {
            get { return _listWrapper[_currentIndex]; }
        }

        public bool MoveNext()
        {
            return _currentIndex++ < _listWrapper.Count;
        }

        public void Reset()
        {
            _currentIndex = -1;
        }
    }
    #endregion
    #region Optional members
    private bool GetValue(object value, out T result)
    {
        if (value is T)
        {
            result = (T)value;

            return true;
        }

        var wrapper = value as Wrapper<T>;
        if (wrapper != null)
        {
            result = wrapper.Value;

            return true;
        }

        result = default(T);
        return false;
    }

    public int Add(object value)
    {
        T result;

        if (GetValue(value, out result))
        {
            _wrappedList.Add(result);
            return _wrappedList.Count - 1;
        }

        return -1;
    }

    public void Clear()
    {
        _wrappedList.Clear();
    }

    public bool Contains(object value)
    {
        T result;

        if (GetValue(value, out result))
            return _wrappedList.Contains(result);

        return false;
    }

    public void CopyTo(Array array, int index)
    {
        for (int listIndex = 0; listIndex < _wrappedList.Count; listIndex++)
        {
            int arrayIndex = listIndex + index;

            if (arrayIndex >= array.Length)
                return;

            array.SetValue(_wrappedList[listIndex], arrayIndex);
        }
    }

    public int IndexOf(object value)
    {
        T result;

        if (GetValue(value, out result))
            return _wrappedList.IndexOf(result);

        return -1;
    }

    public void Insert(int index, object value)
    {
        T result;

        if (GetValue(value, out result))
            _wrappedList.Insert(index, result);
    }

    public void Remove(object value)
    {
        T result;

        if (GetValue(value, out result))
            _wrappedList.Remove(result);
    }
    #endregion
    #region Settings
    public bool AllowEdit { get { return true; } }

    public bool AllowNew { get { return true; } }

    public bool AllowRemove { get { return true; } }

    public bool IsFixedSize { get { return false; } }

    public bool IsReadOnly { get { return false; } }

    public bool SupportsChangeNotification { get { return false; } }

    public bool SupportsSearching { get { return false; } }

    public bool SupportsSorting { get { return false; } }
    #endregion
    #region Not used members
    public void AddIndex(PropertyDescriptor property) { }

    public void ApplySort(PropertyDescriptor property, ListSortDirection direction) { }

    public int Find(PropertyDescriptor property, object key) { return -1; }

    public void RemoveIndex(PropertyDescriptor property) { }

    public void RemoveSort() { }

    public bool IsSorted { get { return false; } }

    public bool IsSynchronized { get { return false; } }

    public ListSortDirection SortDirection { get { return default(ListSortDirection); } }

    public PropertyDescriptor SortProperty { get { return null; } }

    public object SyncRoot { get { return null; } }

    public event ListChangedEventHandler ListChanged;
    #endregion
    #endregion
}

You can use this wrapper as follows:您可以按如下方式使用此包装器:

var myList = new BindingList<string>() { "String 0", "String 1", "String 2" });

myGrid.DataSource = new ListWrapper<string>(myList);
colMyStrings.FieldName = "Value";

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM