2017-02-08 9 views
0

Я работаю над WPF-приложением, используя MVVM, где я повторно использую модель представления для просмотра/создания/редактирования/копирования бизнес-объекта (называемого потоком). В представлении есть около 25 полей, и некоторые из них должны быть отключены в зависимости от того, просматривает ли пользователь/редактирует/... поток. В попытке сохранить вид и модель представления чистой я придумал следующее решение:Как выборочно отключить элементы управления повторно используемой ViewModel в зависимости от варианта использования?

  • Я использую перечислимую GuiAction, содержащий все различные GuiAction с (FlowView, FlowEdit, и т.д ..)
  • у меня есть свойство на модели представления потока типа GuiAction, который представляет ли мы просмотр/редактирование/..
  • Все поля на поток имеет свой IsEnabled атрибут DataBound к свойству GuiAction с преобразователем ControlAvailability взятия название свойства в качестве параметра:

    <CheckBox 
        IsEnabled="{Binding GuiAction, 
         Converter={StaticResource ControlAvailability}, 
         ConverterParameter=Runnable}"></CheckBox> 
    
  • ControlAvailability получает как имя GuiAction, так и имя параметра, и из него он должен возвращать true или false, включение или отключение элемента управления.

Что касается логики в ControlAvailability, моя первоначальная идея, чтобы посмотреть наличие было использовать оператор переключения двухуровневую следующим образом:

public object Convert(object value, ..., object parameter, ...) 
{ 
    GuiAction guiAction = (GuiAction)value; 
    string control = (string)parameter; 

    switch (guiAction) 
    { 
     case GuiAction.FlowView: 
      switch (control) 
      { 
       case "Runnable": 
        return false; 
        break; 
       case "Path": 
        return false; 
        break; 
       ... 
      } 
      break; 
     case GuiAction.FlowEdit: 
      switch (control) 
      { 
       case "Runnable": 
        return true; 
        break; 
       ... 
      } 
      break; 
     ... 
    } 
} 

, но с 7 GuiActions и 25 управления это повернется в сотни строк кода. Я чувствую, что должен быть лучший способ сделать это .. возможно, где-то в плоском файле.

Итак .. Является ли массовое заявление о переключении способом выхода или есть лучшее решение?

+1

Как насчет не повторно использовать ту же модель представления, но и создают определенную по одному для каждого действия? У класса должна быть только одна ответственность.Если один и тот же класс может использоваться во многих разных сценариях в зависимости от значений его свойств, ваш оператор switch неизбежно станет большим. – mm8

+0

Одна из сильных сторон шаблона MVVM - это разделение, позволяющее повторно использовать режимы просмотра для разных видов. Наличие нескольких моделей представления потока для каждого сценария, из которых есть 7, означало бы, что любые модификации модели представления должны были бы выполняться 7 раз. Тогда я предпочел бы иметь большой переключатель где-то :) Я просто думаю, что если эта структура данных (по существу, двумерная матрица) может быть выражена более надежным способом. – jbb

ответ

0

Я закончил просто используя CSV-файл для хранения этих данных. Он идеально подходит для хранения двумерных матриц, подобных этому, и его легко реализовать. Visual Studio не имеет редактора CSV, но у всех моих членов есть Microsoft Excel, который может легко и удобно редактировать и редактировать CSV-файлы. Я внедрил CSV-ридер на основе второго ответа в вопросе this, и я прочитал CSV-файл в словаре, который я использую для поиска значений. В конце концов это мой Convert метод просто выглядит следующим образом:

public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
{ 
    GuiAction guiAction = (GuiAction)value; 
    string control = (string)parameter; 

    //If this is the first time we use the control availability matrix we initialise it 
    if (controlAvailabilityMatrix == null) 
    { 
     controlAvailabilityMatrix = InitControlAvailability(); 
    } 
    try 
    { 
     return controlAvailabilityMatrix[guiAction][control]; 
    } 
    catch (KeyNotFoundException) 
    { 
     throw new AvailabilityNotSetForControlException("Control availability for control " + control + " not set for GUI action " + guiAction); 
    } 
} 
0

Я думаю, что вам нужно это только в преобразователе:

public object Convert(object value, ..., object parameter, ...) 
{ 
    GuiAction guiAction = (GuiAction)value; 
    return guiAction == GuiAction.FlowEdit; 
} 

И связывать только те элементы управления, которые вы хотите отключить, так что вам не нужно связывающее параметр.

Update:

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

public static class StaticData 
{ 
    public static Dictionary<GuiAction, Dictionary<string, bool>> dict = new Dictionary<GuiAction, Dictionary<string, bool>> 
     { 
      { 
       GuiAction.FlowView, new Dictionary<string, bool> 
       { 
        {"Runnable", false}, 
        {"Path", false} 
       } 
      }, 
      { 
       GuiAction.FlowEdit, new Dictionary<string, bool> 
       { 
        {"Runnable", true} 
       } 
      } 
     }; 
} 

И тогда вы можете преобразовать так:

public object Convert(object value, ..., object parameter, ...) 
{ 
    GuiAction guiAction = (GuiAction)value; 
    string control = (string)parameter; 
    return StaticData.dict[guiAction][control]; 
} 
+0

Это было бы хорошо, если бы был только FlowView и FlowEdit, но у меня есть 7 разных GuiActions, которые отключили различные элементы управления в форме – jbb

+0

@jbb. Исходя из вашего требования, я обновил свой ответ. – jannagy02

+0

Это решение действительно решает проблему, но оно относительно похоже на решение коммутатора. Основная проблема, с которой я столкнулся, - это ремонтопригодность. Если я добавлю элемент управления в форму, я должен перейти в семь разных мест в файле кода и заполнить его. – jbb