Хотите способ написать класс со свойством, которое будет возвращать новый экземпляр ViewModel - PullRequest
0 голосов
/ 30 января 2020

У нас есть приложение WPF с целевой страницей, которая содержит около дюжины кнопок, и все они переходят к новым представлениям / моделям просмотра этого типа. Это становится громоздким. У нас есть одна модель представления, которая перечисляет все из них, которые в основном выглядят так:

    private void ExecuteViewProgramCommand()
    {
        OpenViewMessage message = new OpenViewMessage();
        CurrentViewModel = message.ViewModel = ViewModelLocator.ProgramVM;
        Messenger.Default.Send<OpenViewMessage>(message);
    }

Мне никогда не нравилось, как это было сделано, поскольку это нарушает принцип DRY. Единственное, что изменяется в приведенном выше коде во второй строке, где в этом коде то, что изменяется, это ViewModelLocator.ProgramVM. Мне было поручено переделать целевую страницу, сделать ее более организованной, и мы собираемся добавить больше кнопок запуска. Я думаю, что было бы лучше использовать внедрение зависимости. Также я пытаюсь решить вопрос о необходимости изменить дизайн дисплея, чтобы он отображался в списке, а не в разбросанных по алфавиту кнопках и в алфавитном порядке.

Сначала я придумал этот класс:

public class Tile
{
    public string ModuleName { get; set; }
    public NamedViewModelBase ModuleViewModel { get; set; }
}

(NamedViewModelBase - это имя модели представления, которая является общей для всех моделей представления.) Затем я объявил модульный тест для проверки этого и объявил это в модульном тесте:

List<Tile> tiles = new List<Tile>()
{
    new Tile()
    {
        ModuleName = "Program",
        ModuleViewModel = ViewModelLocator.ProgramVM
    },
    new Tile()
    {
        ModuleName = "Organization",
        ModuleViewModel = ViewModelLocator.OrganizationVM
    }
}

Но это быстро стало очевидно, что это неправильно. Присваивание в установщике ViewModelLocator.ProgramVM создаст экземпляр модели представления для Программы. Я не хочу этого, я бы предпочел вызвать его создание, как, например, в ViewModelLocator:

static public ProgramViewModel ProgramVM
{
    get
    {
        if (ServiceLocator.IsLocationProviderSet)
        {
            SimpleIoc ioc = ServiceLocator.Current as SimpleIoc;
            return ioc.GetInstanceWithoutCaching<ProgramViewModel>(Guid.NewGuid().ToString());
        }
        else
        {
            return null;
        }
    }
}

Итак, я думаю, что мне нужно изменить Tile Класс для объявления свойства ModuleViewModel примерно так: public NamedViewModelBase ModuleViewModel { get; }. Но я не знаю, как бы я его реализовал при определении списка. Как правильно решить эту проблему?

Ответы [ 2 ]

1 голос
/ 30 января 2020

Это будет совет psuedo codi sh, который находится на той же дорожке, где вы уже находитесь:

Предполагая, что BaseViewModel является базовым классом для всех ваших отдельных виртуальных машин

  1. Создать словарь
  2. Заполните этот словарь во время запуска приложения (будет выглядеть как ваш список плиток)

    publi c void PreCreateVMs () {dictionary [Key] = new ConcreteViewModelType (); // Продолжаем добавлять новые Vms здесь}

  3. В xaml свяжите все ваши кнопки с одной и той же командой, которая принимает строковый аргумент (или импровизируйте это с помощью Enum). Передайте правильный ключ строки для каждой кнопки. Например: нажатие кнопки «Учетные записи» должно запустить AccountVM, которая хранится с ключом «AccountVM» в словаре.

  4. В обработчике команд - используйте строку, найдите словарь, найдите правильный ViewModel и назначьте этот объект CurrentViewModel

С точки зрения обслуживания - все, что вам нужно добавить новую ViewModel, чтобы обновить xaml с помощью новой кнопки, назначить правильную строку параметра команды. Используйте этот строковый ключ и добавьте правильную ВМ в методе PreCreateVMs.

0 голосов
/ 30 января 2020

Я изменил класс Tile. Я считаю, что мне нужно, чтобы вторым параметром была команда. Я спрашиваю, может ли это быть лучше. Вот новое определение Tile и пример того, как я пытался его реализовать:

public class Tile
{
    public string ModuleName { get; set; }
    //public NamedViewModelBase ModuleViewModel { get; set; }
    public Action ThisCommand { get; set; }
}

А вот как я пытался реализовать его в виде списка:

List<Tile> tiles = new List<Tile>()
{
    new Tile()
    {
        ModuleName = "Program",
        ThisCommand = () => 
        {
            if (ServiceLocator.IsLocationProviderSet)
            {
                SimpleIoc ioc = ServiceLocator.Current as SimpleIoc;
                ioc.GetInstanceWithoutCaching<ProgramViewModel>(Guid.NewGuid().ToString());
            }
        }
    },
    new Tile()
    {
        ModuleName = "Organization",
        ThisCommand = () =>
        {
            if (ServiceLocator.IsLocationProviderSet)
            {
                SimpleIoc ioc = ServiceLocator.Current as SimpleIoc;
                ioc.GetInstanceWithoutCaching<OrganizationViewModel>(Guid.NewGuid().ToString());
            }
        }
    }
};

Я на правильный путь? Должен ли я определить tiles как словарь вместо?

...