【问题标题】:Is there a way to create a collection view that transforms it's source?有没有办法创建一个转换它的源的集合视图?
【发布时间】:2013-07-09 10:36:45
【问题描述】:

我有一个ObservableCollection<T>,它包含一种类型的对象。我需要它作为几个列表控件的来源,但我也想转换数据。为简单起见,假设我有一个 ObservableCollection<int> 并希望获得一个返回字符串的 ICollectionView - 可能只是转换为字符串的整数。

有没有办法创建这样的视图?

一些不错的东西:

var view = new MagicalCollectionView(myCollection, x => x.ToString())?

【问题讨论】:

    标签: c# wpf observablecollection icollectionview


    【解决方案1】:

    集合视图是关于排序、过滤、分组的。它们与数据转换无关。

    实际上,在你的任务解释中没有直接需要这样的集合。您只需要正确设置 view,例如为您的源集合中的项目提供正确的DataTemplate

    public class MyEntity
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
    
    public class MyViewModel
    {
        public ObservableCollection<MyEntity> Entities { get; private set; }
        public ICollectionView EntitiesView
        {
            if (view == null)    
            {
                view = new ListCollectionView(Entities);
            }
            return view;
        }
        private ICollectionView view;
    }
    

    XAML:

    <DataTemplate DataType="{x:Type local:MyEntity}">
        <!-- This "transforms" visual representation of your entity, but the entity itself (and its container) remains unchanged -->
        <TextBlock Text="{Binding Name}"/>
    </DataTemplate>
    

    更新。 根据您的评论,我会将实体包装到视图模型中。此外,这是视图模型的目的:

    public class MyEntityViewModel
    {
        private readonly MyEntity model;
    
        public MyEntityViewModel(MyEntity model)
        {
            this.model = model;
        }
    
        public int MyInt
        {
            get { return model. // some logic to retrieve int ... }
        }
    
        public string MyString
        {
            get { return model. // some logic to retrieve string ... }
        }
    }
    

    然后,我将控件绑定到视图模型集合,而不是模型集合:

    public class MyViewModel
    {
        public MyViewModel(ICollection<MyEntity> entities)
        {
            this.Entities = new ObservableCollection<MyEntityViewModel>(entities.Select(e => new MyEntityViewModel(e)));
    
            // this will keep two collections synchronized:
            this.Entities.CollectionChanged += (sender, args) =>
            {
                switch (e.Action)
                {
                    case NotifyCollectionChangedAction.Add:
                        entities.Add((MyEntity)e.NewItems[0]);
                        break;
                    case NotifyCollectionChangedAction.Remove:
                        entities.Remove((MyEntity)e.OldItems[0]);
                        break;
                    case NotifyCollectionChangedAction.Replace:
                        entities.Remove((MyEntity)e.OldItems[0]);
                        entities.Add((MyEntity)e.NewItems[0]);
                        break;
                    case NotifyCollectionChangedAction.Reset:
                        entities.Clear();
                        break;
                }
            }
        }            
    
        public ObservableCollection<MyEntityViewModel> Entities { get; private set; }
    }
    

    这将使您的数据类远离额外的属性,这些属性仅供查看。

    【讨论】:

    • 不幸的是,这是为了解决我没有源代码的控件中的限制。该控件绑定到集合并显示两个列表。集合可以正常绑定,但列表是使用属性名称提取的,而不是绑定。我无法看到设置模板,我不想向我的数据类添加额外的属性。 XAML 属性类似于 List1Property="MyInt" List2Property="MyString"。视图的想法是在不影响底层集合类型的情况下获取这两个属性。
    • 我的建议是重写控件并控制其运行方式,而不是在不满足您要求的软件的限制下苦苦挣扎。从中长期来看,这将是更好的时间和精力投资。
    • 如果有可能!控制非常复杂 - 至少可能需要一个月的工作 - 并且需要立即解决(并非总是如此!)
    【解决方案2】:

    您可以使用 LINQ 进行投影

    myCollection.Select(x=> int.Parse(x))
    

    将解析集合中的每个元素并返回一个整数

    【讨论】:

    • 现在尝试在源集合中插入一些内容并在视图中反映更改...
    • 丹尼斯打败了我——它需要保持同步。
    【解决方案3】:

    我基本同意 Dennis 的观点,但是,在这种情况下,使用绑定转换器对底层绑定值进行最终转换可能会对您有所帮助。

    我假设您有一个类型的集合,并且想要在不同位置对数据进行不同的、实时的投影。

    您可以在每种情况下绑定到同一个集合,并为每种情况“插入”不同的自定义转换器,可能在自定义 DataTemplate 中。

    http://www.silverlightshow.net/items/Data-Conversion-in-Silverlight-2-Data-Binding.aspx

    Silverlight 演示,但它是一样的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多