Рекомендовать лучший подход в этой ситуации - PullRequest
2 голосов
/ 23 июля 2010

Я экспериментирую с MVVM и не могу полностью обдумать это.

У меня есть представление (окна), в котором есть несколько повторяющихся элементов управления.

Допустим, у меня есть 4 пары текстовых полей - кнопок.Их поведение должно быть таким же, после нажатия кнопки парное текстовое поле говорит: «Привет, мир!»

Я попробовал несколько вариантов, о которых мог подумать:

  1. Одна ViewModel, 4 строковых свойствапривязано к текстовым полям, 1 команда
    • Когда я связываю каждую кнопку с одной и той же командой, я не могу сказать, какое свойство необходимо установить.
    • Передача enum в CommandParameter выглядит неловко.
  2. Один ViewModel и UserControl, который содержит текстовое поле и кнопку, повторяется 4 раза.
    • Теперь мне нужно выставить все свойства, такие как Command, CommandParameter, Text и т. Д. Похоже на большую работу.
    • Все еще не могу сказать, какое свойство необходимо обновить после щелчка.
  3. Каждый UserControl имеет ViewModel
    • Это решает нажатие кнопки и настройка свойства, но теперь я понятия не имею, как извлечь текст из вложенных ViewModel в окно ViewModel.

Есть ли другой способ?Я подозреваю, что DataTemplates могут быть полезны, но я не уверен, как.

Ответы [ 3 ]

2 голосов
/ 23 июля 2010

То, что вы описываете, является настолько абстрактной и надуманной идеей, что она не гарантирует MVVM. Вы говорите о TextBox es и Buttons, которые являются «View», а не мышлением MVVM. Вы почти всегда начинаете с модели.

Здесь нет «модели» как таковой; ваша спецификация буквально установить значение TextBox на Button клик. Казалось бы, случайный список из 4 предметов (выбранный из ниоткуда) и бесполезный TextBox ничего не значат.

Если оставить это в стороне и предположить, что у вас есть набор из 4 бизнес-объектов, в каждом из которых есть поле, редактируемое пользователем, и действие, которое пользователь может инициировать, вы сделаете следующее:

  • Создать класс ViewModel для представления элемента - например, MyItemModel
  • Создать класс ViewModel для представления набора элементов (вероятно, он просто вернет коллекцию первого) - например, AllMyItemsListModel

Тогда для просмотра:

  • Создать ItemsControl, с ItemsSource, привязанным к экземпляру «коллекции» второго класса ViewModel
  • Для каждого ItemTemplate, есть шаблон или UserControl для каждого элемента
  • В шаблоне или UserControl свяжите свойство Text TextBox с соответствующим свойством первого класса
  • Свяжите свойство Button Command со свойством первого класса, возвращая ICommand - используя RelayCommand, например

Я не знаю, что вы имеете в виду под «извлечением текстов из вложенных ViewModel в окно ViewModel» - что это значит и почему вы хотите это сделать?

Надеюсь, это поможет.

1 голос
/ 24 июля 2010

Нет необходимости создавать отдельную ViewModel для повторно используемого элемента управления, который имеет такое простое поведение. Просто добавив несколько DependencyProperties и обработчик событий в простой UserControl, вы можете повторно использовать логику и устанавливать только те свойства, которые на самом деле различны для каждого экземпляра. Для XAML UserControl вам просто нужно подключить TextBox к DependencyProperty и обработчику Button to Click.

<DockPanel>
    <Button Content="Reset" Click="Button_Click"/>
    <TextBox Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=Text}"/>
</DockPanel>

Код для UserControl просто должен определить свойства, которые могут быть привязаны извне, и обработчик для сброса текста.

public partial class ResetTextBox : UserControl
{
    public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
        "Text",
        typeof(string),
        typeof(ResetTextBox),
        new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }

    public static readonly DependencyProperty ResetTextProperty = DependencyProperty.Register(
        "ResetText",
        typeof(string),
        typeof(ResetTextBox),
        new UIPropertyMetadata(String.Empty));

    public string ResetText
    {
        get { return (string)GetValue(ResetTextProperty); }
        set { SetValue(ResetTextProperty, value); }
    }

    public ResetTextBox()
    {
        InitializeComponent();
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        Text = ResetText;
    }
}

Затем, чтобы использовать элемент управления, вам просто нужно привязать свои свойства строки ViewModel и установить текст по умолчанию, который должен применяться при сбросе, который может быть здесь либо жестко задан, либо привязан к другим свойствам ВМ.

<StackPanel>
    <local:ResetTextBox ResetText="One" Text="{Binding Name1}"/>
    <local:ResetTextBox ResetText="Two" Text="{Binding Name2}"/>
    <local:ResetTextBox ResetText="Three" Text="{Binding Name3}"/>
</StackPanel>
1 голос
/ 23 июля 2010

Номер 3. За исключением того, что будет только один UserControl с viewmodel, а затем главная страница, на которой будет несколько экземпляров этого UserControl. Если главное окно нуждается в информации из UserControl, вы можете передать его через события или использовать что-то вроде MVVM Light и его класс мессенджера.

...