Как я могу заменить статический ObservableCollection, чтобы он был доступен для всех окон способом MVVM - PullRequest
1 голос
/ 29 февраля 2012

Atm Я получил класс (somerandomclasss) со статической коллекцией ObservableCollection:

public static ObservableCollection<PersonViewModel> thepeoplelist = new ObservableCollection<PersonViewModem>();

Однако я конвертирую свой проект в MVVM и, конечно, это не хороший способ заполнить все мои элементы управления (списочные просмотры)в основном) У меня есть несколько окон, которые используют этот источник таким образом.

private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
    lsvallthepeople.ItemSource = somerandomclasss.thepeoplelist;
}

В представлении списка отображаются все люди с информацией.Однако я не спорю с MVVM, и я не нашел хорошего способа работы без общедоступной статической ObservableCollection, однако есть окно, в котором вы получили список, в котором вы можете редактировать людей, они обновляются в SQLв базе данных и в PersonViewModel (который получил INotifyPropertyChanged).

Если вам нужна дополнительная информация, не стесняйтесь спрашивать у:).

Ответы [ 3 ]

3 голосов
/ 29 февраля 2012

Я полагаю, что вы спрашиваете: «Какой лучший способ поделиться списком элементов в нескольких представлениях в MVVM?» так что я отвечу на вопрос таким образом.

Предположим, у вас есть сервис, который позволяет получить список людей. Вы назвали его «PersonViewModel», но, возможно, вы путаете объектную сущность с ViewModel. В MVVM у вас есть представление, представляющее элемент управления или экран пользовательского интерфейса. Затем у вас есть ViewModel, которая связывается с представлением и соединяет представление с моделью данных / предметной области. ViewModel может иметь ряд общедоступных свойств, к которым привязывается View, включая методы, которые вызывают службы для заполнения этих свойств из вашей модели данных. В вашем случае у меня будет View + ViewModel, а ViewModel имеет свойство ObservableCollection класса "Person".

Следующий код является пересказом того, как он может выглядеть на самом деле. Не все реализовано.

public class MyViewModel : INotifyPropertyChanged
{
    public ObservableCollection<Person> People { get; set; }

    public MyViewModel()
    {
        this.People = new ObservableCollection<Person>();
        this.LoadPeople();
    }

    private void LoadPeople()
    {
        this.People.Clear();
        // Have your logic here that loads the people collection
    }
}

Что касается управления одним списком, я рекомендую кэшировать коллекцию людей в некотором статическом классе или синглтоне, который доступен для ваших моделей представлений. Тогда приведенный выше метод LoadPeople можно просто извлечь из кеша. Вы можете даже лениво загрузить кэш, чтобы он не выполнял запрос на обслуживание до его первого доступа.

internal static class SystemContext
{
    private static ObservableCollection<Person> _people = null;
    public static ObservableCollection<Person> People
    {
        get
        {
            if( _people == null )
            {
                _people = new ObservableCollection<Person>();
                // load the list here from a service or something
            }

            return _people;
        }
    }
}

Итак, в вашей ViewModel LoadPeople будет выглядеть примерно так:

public void LoadPeople()
{
    this.People.Clear();

    foreach( Person person in SystemContext.People )
    {
        this.People.Add( person );
    }
}

Ваш пользовательский интерфейс будет выглядеть примерно так:

<ListBox 
    ItemsSource={Binding Path=People, Mode=OneWay}
    SelectedItem={Binding Path=SelectedPerson, Mode=TwoWay}
    >
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Vertical">
                <TextBlock Text="{Binding Path=PersonName, Mode=OneWay}" />
                <TextBlock Text="{Binding Path=DateOfBirth, Mode=OneWay}" />
                <!-- etc -->
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>
2 голосов
/ 29 февраля 2012

Вы можете использовать привязку Static для привязки ItemsSource вместо ручной установки в коде

<ListBox ItemsSource="{Binding Source={
    x:Static local:somerandomclasss.thepeoplelist}}" ... />

или выставьте свойство, которое возвращает коллекцию из вашей ViewModel и связывается с этим свойством

public class MyViewModel
{
    public ObservableCollection<PersonViewModel> PersonList
    {
        get { return somerandomclasss.thepeoplelist; }
    }

    ...
}

<ListBox ItemsSource="{Binding PersonList}" ... />
1 голос
/ 29 февраля 2012

Вы, вероятно, должны иметь это как сервис или репозиторий, который внедряется в каждую модель представления (как абстракцию), которая требует список.

Поскольку вы хотите заполнить этот список только один раз, вы можете сделатьэто в конструкторе реализации службы / репозитория или использовать метод кэширования в методе services GetList.

Поскольку вы всегда хотите передать один и тот же экземпляр каждой модели представления, вы должны использовать либо одноэлементный шаблон, либо зарегистрировать абстракцию (например, IPeopleRepository) для конкретного экземпляра, если используете контейнер IoC.

Поскольку это будет служба / репозиторий, вы должны вернуть тип, который не зависит от технологии представления, то есть IEnumerable<T> или IList<T>, и использовать его для создания наблюдаемых коллекций в каждой модели представления..

...