【问题标题】:data binding of collections集合的数据绑定
【发布时间】:2012-10-27 06:47:37
【问题描述】:

我只想将一个集合绑定到另一个集合: 假设有一个

List<string> original = new List<string>();

还有一个

List<string> extended = 
           new List<string>(from curItem in originals select curItem + "_extension");

所以扩展后的项目和原来的一样,只是末尾有一个“_extension”。

我想要的是将扩展绑定到原始,这样如果原始更改,扩展也会更改。

我知道我可以使用事件并每次都重新创建扩展。 但我认为这样效率不高。

编辑: 可以说:原始很大,重新创建扩展的单个元素太累了,创建单个元素也太累了。 所以我希望有两个列表(或集合),其中 on 观察另一个并添加或删除更改,例如 Wpf 中的数据绑定,但添加扩展。

【问题讨论】:

    标签: c# data-binding collections


    【解决方案1】:

    您可以使用 System.ComponentModel 上的 BindingList&lt;T&gt; 类来实现这一点...也许这就像用锤子杀死一只苍蝇,但可以用于更复杂的示例。

    我认为您可以像这样制作扩展方法

    static class ExtensionMethods
    {
        public static IEnumerable<string> Extensions(this IEnumerable<string> strs)
        {
            foreach (var str in strs)
            {
                yield return str + "_extension";
            }
        }
    }
    

    您可以在每个IEnumerable&lt;String&gt; 上使用它:

    foreach (var x in original.Extensions())
    {
        Console.WriteLine(x);
    }
    

    【讨论】:

    • BindingList 可能是我正在寻找的东西:它提供了报告更改的方法。但是我仍然需要为 extended 创建一个我自己的 List 类扩展,它可以处理这些变化。没有什么已经为此实施了吗?
    • 谢谢,但也许我会使用 ObservableCollection。另一方面,我不需要扩展扩展的 List 类,因为我需要一个方法来处理更改的内容...
    【解决方案2】:

    我认为有两种不同的方法:

    1. 在原始更改时更改extended
    2. 根本不创建extended,而是创建一些类,这将 在每个查询中添加“_extention”。

    使用 bindingList,第一种方法将足够有效。

    public class MyClass
    {
        private BindingList<string> original = new BindingList<string>();
        private List<string> extended = new List<string>();
    
        public BindingList<string> Original
        {
            get
            {
                return original;
            }
        }
    
        public IEnumerable<string> Extended
        {
            get
            {
                return extended;
            }
        }
    
        public MyClass()
        {
            original.ListChanged += OnChanging;
        }
    
        void OnChanging(object sender, ListChangedEventArgs e)
        {
            switch (e.ListChangedType)
            {
                case ListChangedType.ItemAdded:
                    extended.Add(original[e.NewIndex] + "_extention");
                    break;
                case ListChangedType.ItemChanged:
                    extended[e.NewIndex] = original[e.NewIndex] + "_extention";
                    break;
                case ListChangedType.ItemDeleted:
                    extended.RemoveAt(e.NewIndex);
                    break;
                case ListChangedType.ItemMoved:
                    string tmp = extended[e.NewIndex];
                    extended[e.NewIndex] = extended[e.OldIndex];
                    extended[e.OldIndex] = tmp;
                    break;
                case ListChangedType.Reset:
                    extended = new List<string>();
                    foreach (string originalItem in original)
                    {
                        extended.Add(originalItem + "_extention");
                    }
                    break;
            }
        }
    }
    

    第二种方法如下所示:我们创建自己的类,其中包含指向originals的链接

    public class MyExtendedList : IEnumerable
    {
        private List<string> original;
        public MyExtendedList(List<String> original)
        {
            this.original = original;
        }
    
        public IEnumerator GetEnumerator()
        {
            return new ExtendedEnum(original);
        }
    }
    
    public class ExtendedEnum : IEnumerator
    {
        private List<string> original;
        private int position = -1;
        public ExtendedEnum(List<String> original)
        {
            this.original = original;
        }
    
        public object Current
        {
            get
            {
                return CurrentString;
            }
        }
    
        public bool MoveNext()
        {
            position++;
            return (position < original.Count);
        }
    
        public void Reset()
        {
            position = -1;
        }
    
        public String CurrentString
        {
            get
            {
                try
                {
                    return original[position] + "_extension";
                }
                catch (IndexOutOfRangeException)
                {
                    throw new InvalidOperationException();
                }
            }
        }
    }
    

    【讨论】:

    • 检查return Current; 行,我想应该是return CurrentString
    【解决方案3】:

    创建自己的课程:

    public class MyClass
    {
       private string _Item;
       public string Item 
       { 
           get { return _Item; }
           set 
           {
               if (_Item != value)
               {
                   _Item = value;
                   _ItemWithExtension = _Item + "_extension";
               }
           }
       }
       private string _ItemWithExtension;
       public string ItemWithExtension
       {
          get { return _ItemWithExtension; }
       }
    }
    
    var extended = 
               new List<MyClass>(from curItem in originals select 
                                new MyClass()
                                {
                                    Item = curItem
                                }
                               );
    

    【讨论】:

    • 更改原件对扩展有何影响?
    • @Amiram Korach:您的解决方案的问题是,每次访问时都会重新创建新项目。但是我觉得这也太累了。我希望扩展观察原件并及时添加新项目。
    • @Amiram:如果我这样做extended[0].ItemWithExtension 会怎样?我会得到 *_extension_extension
    • @DmitryDovgopoly,当您更改 Item 时,ItemWithExtension 将更改,但我会改进我的答案。
    • @Amiram Korach 但我认为,如果原件发生更改,扩展不会更新...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-14
    • 2011-01-03
    • 2011-05-14
    • 2010-11-25
    • 1970-01-01
    • 1970-01-01
    • 2014-02-15
    相关资源
    最近更新 更多