c# - 自定义 CompositeCollection 不工作

标签 c# .net wpf windows-phone-8

我试过编写自定义 CompositeCollectionCollectionContainer几次,我正要放弃。这就是我所拥有的。看起来很简单。

主页.xaml

<phone:PhoneApplicationPage.Resources>
    <vm:MainViewModel x:Key="ViewModel"/>
</phone:PhoneApplicationPage.Resources>

<phone:Panorama DataContext="{StaticResource ViewModel}">        
    <phone:Panorama.ItemsSource>
        <app:CompositeCollection>
            <app:CompositeContainer Collection="{Binding People}"/>
            <models:PersonModel FirstName="John" LastName="Doe"/>
        </app:CompositeCollection>
    </phone:Panorama.ItemsSource>

    <phone:Panorama.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <TextBlock Text="{Binding FirstName}"/>
                <TextBlock Text="{Binding LastName}"/>
            </StackPanel>
        </DataTemplate>
    </phone:Panorama.ItemTemplate>
</phone:Panorama>

复合集合.cs

namespace PanoramaApp1
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;

    public class CompositeCollection : ObservableCollection<object>
    {
        Collection<IEnumerable> _collections;

        public CompositeCollection()
            : base()
        {
            _collections = new Collection<IEnumerable>();
        }

        public CompositeCollection(IEnumerable<object> collection)
            : this()
        {
            if (null == collection)
            {
                throw new ArgumentNullException("collection");
            }
            foreach (object obj in collection)
            {
                base.Add(obj);
            }
        }

        public CompositeCollection(List<object> list)
            : this()
        {
            if (null == list)
            {
                throw new ArgumentNullException("list");
            }
            foreach (object obj in list)
            {
                base.Add(obj);
            }
        }

        protected override void ClearItems()
        {
            base.Clear();
            _collections.Clear();
        }

        protected override void InsertItem(int index, object item)
        {
            CompositeContainer container = item as CompositeContainer;
            if (null != container && null != container.Collection)
            {
                InsertContainer(index, container);
            }
            else
            {
                base.InsertItem(index, item);
            }
        }

        private void InsertContainer(int index, CompositeContainer container)
        {
            IEnumerable collection = _collections[index] = container.Collection;
            foreach (object obj in collection)
            {
                base.InsertItem(index++, obj);
            }
        }

        protected override void RemoveItem(int index)
        {
            IEnumerable collection = _collections[index];
            if (null != collection)
            {
                RemoveContainer(index, collection);
            }
            else
            {
                base.RemoveItem(index);
            }
        }

        private void RemoveContainer(int index, IEnumerable collection)
        {
            foreach (object obj in collection)
            {
                base.RemoveItem(index++);
            }
            _collections.RemoveAt(index);
        }

        protected override void SetItem(int index, object item)
        {
            RemoveItem(index);
            InsertItem(index, item);
        }
    }
}

复合容器.cs

namespace PanoramaApp1
{
    using System.Collections;
    using System.Windows;

    public class CompositeContainer : DependencyObject
    {
        public IEnumerable Collection
        {
            get { return (IEnumerable)GetValue(CollectionProperty); }
            set { SetValue(CollectionProperty, value); }
        }

        public static readonly DependencyProperty CollectionProperty =
            DependencyProperty.Register(
            "Collection",
            typeof(IEnumerable),
            typeof(CompositeContainer),
            new PropertyMetadata(null));
    }
}

MainViewModel.cs

using Models;
using System.Collections.ObjectModel;

namespace ViewModels
{
    public class MainViewModel
    {
        public MainViewModel()
        {
            this.People = new ObservableCollection<object>();
            People.Add(new PersonModel("Jane", "Doe"));
            People.Add(new PersonModel("Joe", "Doe"));
            People.Add(new PersonModel("James", "Doe"));
        }

        public ObservableCollection<object> People { get; private set; }
    }
}

PersonModel.cs

using System.ComponentModel;

namespace Models
{
    public class PersonModel : INotifyPropertyChanging, INotifyPropertyChanged
    {
        public event PropertyChangingEventHandler PropertyChanging;

        public event PropertyChangedEventHandler PropertyChanged;

        private string _firstName;

        private string _lastName;

        public PersonModel(string firstName)
        {
            this.FirstName = firstName;
        }

        public PersonModel(string firstName, string lastName)
            : this(firstName)
        {
            this.LastName = lastName;
        }

        public string FirstName
        {
            get { return _firstName; }
            set
            {
                RaisePropertyChanging("FirstName");
                _firstName = value;
                RaisePropertyChanged("FirstName");
            }
        }

        public string LastName
        {
            get { return _lastName; }
            set
            {
                RaisePropertyChanging("LastName");
                _lastName = value;
                RaisePropertyChanged("LastName");
            }
        }

        private void RaisePropertyChanging(string propertyName)
        {
            if (null != PropertyChanging)
            {
                PropertyChanging(this, new PropertyChangingEventArgs(propertyName));
            }
        }

        private void RaisePropertyChanged(string propertyName)
        {
            if (null != PropertyChanged)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

如果我在 xaml 中注释掉 PersonModel 对象,应用程序将启动,但不会填充全景图。如果我不加注释,我会得到一个非常无用的异常,说 PersonModel 对象“无法实例化”。 ItemsSource ItemsControl 的属性类型为 IEnumerable看来我正在正确枚举容器。 帮助?请?哈哈


编辑:谢谢,无参数构造函数解决了第一个问题。第二个问题仍然存在:它现在确实用 PersonModel 对象填充了第二个 panoramaitem,但第一个 panoramaitem 仍然是空的。似乎它将整个第一个 panoramaitem 绑定(bind)到 IEnumerable 而不是插入单个元素。

设计师展示了这个:i.imgur.com/4fAPe0N.jpg模拟器显示:i.imgur.com/UzdyMqk.png i.imgur.com/SWJZ28H.png

最佳答案

您在 XAML 中初始化一个 PersonModel,它将调用您的代码中不存在的默认构造函数 => 只需将其添加到 PersonModel.cs 即可解决该部分:

public PersonModel() {}

xaml 中的参数不会用作构造函数参数,但它们会在创建对象后使用属性 setter 设置值,就像

new PersonModel() { FirstName="John", LastName="Doe" };

关于c# - 自定义 CompositeCollection 不工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22681836/

相关文章:

c# - 如何使用 StringCollection 填充(标记为选中)checkedListBox

c# - 如何处理调用了异步方法的对象?

c# - DataGrid行背景色MVVM

wpf - WPF到底是什么?

c# - 如何在 WPF 中将 DataGrid 导出到 Excel

c# - Entity Framework .NET Core 2.0 查询在执行子查询时挂起

c# - 如何在 ASP.NET Core Identity 中注销用户

c# - 代码契约(Contract)的好处

.net - VS2010项目中资源文件的路径

c# - 如何根据新的安全策略在 .Net 中发送电子邮件?