Правильная реализация MVVM для данных, отображаемых в двух представлениях с разными методами отображения - PullRequest
1 голос
/ 19 июля 2011

Я посмотрел вокруг в Google и не могу определить правильный протокол для отображения этих данных.

Мое приложение отображает одни и те же данные ядра в двух разных представлениях (холст и древовидная структура) рядом, но для каждого требуется разная компоновка. Холст просто использует плоский ObservableList для отображения пользовательских объектов на экране. Древовидная структура предоставит категоризированный список этих данных. Из-за необходимости иерархии в одном представлении, а не в другом, имеет ли смысл создавать дополнительные модели представлений для переноса данных?

Я бы хотел как можно больше использовать модели представлений, но не создавать классы "бога".

Пример:

Canvas:
- - - - - - - - - - - - - - - 
|    Person1      Person2   |
|  Person3      Person4     |
- - - - - - -  - - - -  - - -

TreeView:
People:
 -Adults
   -Person1
   -Person4
 -Children
   -Person2
 -Teens
   -Person3

Извините за ужасный рисунок.

Ответы [ 4 ]

2 голосов
/ 19 июля 2011

я думаю, что вы можете добиться этого, используя простой запрос linq ...

вот пример .. Я сделал это в коде файла, вы можете сделать нечто подобное в вашей viewmodel

public partial class Window1 : UserControl
    {
        List<Person> CanvasDatasource { get; set; }
        List<Category> TreeViewDatasource { get; set; }

        public Window1()
        {
            InitializeComponent();
            TreeViewDatasource = new List<Category>();

            for (int i = 0; i < 5; i++)
            {
                Category c = new Category();
                c.Name = "category" + i;
                for (int j = 0; j < 5; j++)
                {
                    c.persons.Add(new Person { Name = "Person " + j });
                }

                TreeViewDatasource.Add(c);
            }

            CanvasDatasource = TreeViewDatasource.SelectMany(i => i.persons.Select(j => j)).ToList();

        }


    }

    class Category
    {
        public Category()
        {
            persons = new List<Person>();
        }
        public string Name { get; set; }
        public List<Person> persons { get; set; }
    }

    class Person
    {
        public string Name { get; set; }
    }

В «TreeViewDatasource» вы получите классифицированных лиц, а в «CanvasDatasource» вы получите плоский список людей

2 голосов
/ 19 июля 2011

@ JMcCarty Вы попросили меня объяснить мой комментарий выше, но это было слишком много, чтобы добавить комментарий

Вы бы получили ObservableCollection<People> из своего источника данных и выставили его через одно открытое свойство для Canvas.,Затем вы создадите второе открытое свойство для TreeView и разберете в нем свою коллекцию People.

Примерно так:

public class PeopleTreeItem
{
    public string Header;
    public ObservableCollection<object> Items;

    public PeopleTreeItem(string header, IEnumerable<object> items)
    {
        Header = header;
        Items = new ObservableCollection<object>() { items };
    }
}

public class SomeViewModel : ViewModelBase
{
    private ObservableCollection<Person> _peopleList;
    private PeopleTreeItem _peopleTree;

    public ObservableCollection<Person> PeopleList
    {
        get { return _people; }
    }

    public PeopleTreeItem PeopleTree
    {
        get 
        { 
            if (_peopleTree == null)
            {
                _peopleTree = new PeopleTreeItem();

                _peopleTree.Add(new PeopleTreeItem("Adults", PeopleList.Where(p => p.Type == "Adult")));
                _peopleTree.Add(new PeopleTreeItem("Teens", PeopleList.Where(p => p.Type == "Teen")));
                _peopleTree.Add(new PeopleTreeItem("Children", PeopleList.Where(p => p.Type == "Child")));
            }
            return _people; 
        }
    }
2 голосов
/ 19 июля 2011

Я думаю, вам просто нужно создать еще один объект на основе Списка людей, например:

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using GalaSoft.MvvmLight;

namespace XXXX.ViewModel
{
    public class MainViewModel : ViewModelBase
    {
        private ObservableCollection<Person> _people;
        public ObservableCollection<Person> People
        {
            get { return _people; }
            set
            {
                if (value == _people) return;
                _people = value;
                RaisePropertyChanged("People");
                RaisePropertyChanged("HierarchyPeople");
            }
        }

        public HierarchyPeople HierarchyPeople
        {
            get
            {
                //=====> Change _people to new format
                return new HierarchyPeople(_people);
            }
        }
    }

    public class Person
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public Gategory Gategory { get; set; }
    }

    public class Gategory
    {
    }

    public class HierarchyPeople : Dictionary<Gategory, List<Person>>
    {
        public HierarchyPeople(ObservableCollection<Person> people)
        {
            var categories = people.Select(p => p.Gategory).Distinct();

            foreach (var cat in categories)
                this.Add(cat, people.Where(p => p.Gategory == cat).ToList());
        }
    }
}
0 голосов
/ 19 июля 2011

Джош Смит предоставил отличную статью о том, как использовать MVVM с TreeViews . Используя этот подход, я бы порекомендовал модель вида TreeView. Хотя теоретически вы могли бы объединить эти две проблемы, проблемы могли бы быть перепутаны.

...