Я все еще не получаю MVVM!

Возможно, я делал разработку Flex с Платформами как Дымчатый топаз слишком долго, но я все еще не получаю MVVM. Я знаю, что Дымчатый топаз является платформой, и MVVM является шаблоном разработки, но что я сравниваю, вот реализации Дымчатых топазов шаблонов разработки, главным образом образцовый контроллер представления и шаблон "команда". Не понимайте меня превратно, я думаю, что идея связать представление с моделью представления является прекрасной, и преимущества в тестируемости и рабочем процессе разработчика-программиста являются большими. Но существует две вещи, которые беспокоят меня: каждый программирует все мои действия с Командами, который, по тому, как также ограничено меня от Дымчатого топаза. Только в Дымчатом топазе путем они реализовали шаблон "команда", принес Вам пользу наличия централизованного контроллера для всех Ваших команд, которые Вы, кажется, не получаете с MVVM, если я не пропускаю что-то. И если я думал, реализовывая команды в Дымчатом топазе, было замысловатым в MVVM, очень хуже, я означаю иметь необходимость создать частные классы, которые реализуют ICommand для всего, что я делаю походит на слишком много. И затем у Вас есть проблема, что не все средства управления реализуют команды так, например, при использовании ListBox который я использую много, Вам не повезло; существуют обходные решения, но все довольно замысловатые.

Другой вещью, которая беспокоит меня, является коммуникация между Моделями Представления. В Контроллере Представления стандартной модели Вы собираете все Вы информация о централизованной модели, которая наблюдается представлениями, но это, кажется, не имеет место с MVVM, по крайней мере, не в примерах, которые я видел. Так, например, если Вы имеете контроль со списком, который Вы используете для выбора объекта, который затем используется в качестве источника для различных взглядов и последовательных действий, мне не ясно, как Вы уведомляете каждое из изменений без централизованной модели.

Я знаю о MVVMFoundation и работе Tom Ershamam о Командах WPF Везде. Названный мной старомодный, но я думаю что для реального понимания шаблона, необходимо создать приложение, которое использует его с нуля. Который является тем, что я делаю, но все время, я продолжаю думать, что я должен пропускать что-то существенное, потому что я, кажется, не могу подавить шумы этой небольшой речи в голове, которая продолжает говорить мне, должен быть лучший путь.

8
задан Julio Garcia 24 February 2010 в 10:07
поделиться

5 ответов

Независимо от фреймворка/архитектуры/шаблона, вам всегда понадобится что-то, что реагирует на нажатие кнопки, на панели инструментов/меню или на простой форме. И вам нужно что-то, что говорит, должна ли кнопка/меню быть включена. Для этого хорошо подходит интерфейс ICommand. Я согласен с Petoj, вам не нужен новый класс. Я написал простую реализацию, которая принимает 1 или 2 делегата, один для фактического ответа на нажатие (метод Execute) и дополнительный для статуса "включено" команды. Таким образом, ViewModel не загромождается.

Но я согласен, что это не централизованное хранилище команд. Но действительно ли оно вам нужно? Я предпочитаю, чтобы команды, специфичные для одной части приложения, находились в соответствующей модели представления, с соответствующими событиями, поднимаемыми, когда остальная часть приложения должна быть уведомлена.

Для списка я привязываю свойство SelectedItem к свойству во ViewModel. С помощью INotifyPropertyChanged любая часть вашего кода может реагировать на изменение.

Связь между ViewModel - хороший вопрос. Если вам нужны разные представления на одном экране, вы можете иметь "супер" модель представления, которая содержит модель представления каждого представления. Существует довольно много MVVM-фреймворков. Я использовал части MVVM helpers Марка Смита, который является довольно легким и полезным.

3
ответ дан 5 December 2019 в 21:18
поделиться

Хорошо, если написать новую команду, которая реализует ICommand, кажется, немного переборщить с kill, взгляните на этот класс: VB.NET: {{1 }} Открытый класс RelayCommand Реализует ICommand

#Region " Declarations"
    Private mCanExecute As Predicate(Of Object)
    Private mExecute As Action(Of Object)
#End Region

#Region " Constructors"
    Public Sub New(ByVal canExecute As Predicate(Of Object), ByVal execute As Action(Of Object))
        mCanExecute = canExecute
        mExecute = execute
    End Sub

    Public Sub New(ByVal execute As Action(Of Object))
        mCanExecute = Nothing
        mExecute = execute
    End Sub
#End Region

#Region " Events"
    Public Custom Event CanExecuteChanged As EventHandler Implements System.Windows.Input.ICommand.CanExecuteChanged
        AddHandler(ByVal value As EventHandler)
            AddHandler CommandManager.RequerySuggested, value
        End AddHandler
        RemoveHandler(ByVal value As EventHandler)
            RemoveHandler CommandManager.RequerySuggested, value
        End RemoveHandler
        RaiseEvent(ByVal sender As Object, ByVal e As System.EventArgs)
            Throw New ApplicationException("Can't raise custom command!")
        End RaiseEvent
    End Event
#End Region

#Region " Public Methods"
    Public Function CanExecute(ByVal parameter As Object) As Boolean Implements System.Windows.Input.ICommand.CanExecute
        If (mCanExecute Is Nothing) Then
            Return True
        End If
        Return mCanExecute(parameter)
    End Function

    Public Sub Execute(ByVal parameter As Object) Implements System.Windows.Input.ICommand.Execute
        mExecute(parameter)
    End Sub
#End Region

End Class

C #

public class RelayCommand : ICommand
{

    #region Declarations
    private Predicate<object> mCanExecute;
    private Action<object> mExecute;
    #endregion

    #region Constructors
    public RelayCommand(Predicate<object> canExecute, Action<object> execute)
    {
        mCanExecute = canExecute;
        mExecute = execute;
    }

    public RelayCommand(Action<object> execute)
    {
        mCanExecute = null;
        mExecute = execute;
    }
    #endregion

    #region Events
    public event EventHandler CanExecuteChanged {
        add {
            CommandManager.RequerySuggested += value;
        }
        remove {
            CommandManager.RequerySuggested -= value;
        }
    }
    #endregion

    #region Public Methods
    public bool CanExecute(object parameter)
    {
        if ((mCanExecute == null)) {
            return true;
        }
        return mCanExecute(parameter);
    }

    public void Execute(object parameter)
    {
        mExecute(parameter);
    }
    #endregion

}

, и для его использования просто выставьте свойство типа ICommand, которое возвращает новую RelayCommand с делегатами функции ...

vb.net

Private mDeleteCommand As ICommand

Public ReadOnly Property DeleteCommand() As ICommand
    Get
        If (mDeleteCommand Is Nothing) Then
            mDeleteCommand = New RelayCommand(AddressOf CanDeleteTodo, AddressOf DeleteTodo)
        End If
        Return mDeleteCommand
    End Get
End Property

C #

private ICommand mDeleteCommand;
public ICommand DeleteCommand {
    get {
        if ((mDeleteCommand == null)) {
            mDeleteCommand = new RelayCommand(CanDeleteTodo, DeleteTodo);
        }
        return mDeleteCommand;
    }
}
3
ответ дан 5 December 2019 в 21:18
поделиться

Только пользователь, запускающий веб-сервер dameon, должен иметь разрешения на запись в каталог. И вам, конечно, не нужны разрешения на выполнение для каталога, в который загружаются пользователи.

-121--4320790-

Обычно настройки папки устанавливаются один раз и все. Это довольно бессмысленно продолжать устанавливать разрешения папки 777 через PHP, когда вы уже установили его 777.

-121--4320791-

OK, чтобы дать этому потоку некоторый вид закрытия для будущей ссылки. Во-первых, большое спасибо за ответы. Команда RelayCommand действительно хорошая идея; это действительно многое упрощает и облегчает тестирование и работу. Похоже, это путь. Привязка к SelectedItem также решает проблему отсутствия поддержки команд в ItureControl. Что касается связи между ViewModels, я не убежден, что наличие супервидовой модели решает мою проблему, поскольку она связывает модель с моим визуальным деревом. Кроме того, я не нашел способа в этой структуре иметь чистый, независимый от объекта способ связи между всеми моделями представлений в различных иерархиях. Итак, я пытаюсь сначала создать централизованную модель, которая является синглтоном, реализующим интерфейс INotifyPropertyChanged. Затем ViewModels может иметь экземпляр этой модели и действовать на него, распространяя соответствующие изменения свойств с помощью нашего старого доброго друга образца Observer. Кажется, работает хорошо, хотя я немного беспокоюсь о круговых ссылках. Что вы думаете?

0
ответ дан 5 December 2019 в 21:18
поделиться

Привет, Хулио,

Похоже, это старый пост, но мне очень нравится твой вопрос.

В последнее время я занимаюсь гибким программированием и WPF. Я хорошо знал структуру Cairngorm (скажем, [C]), научился использовать модель представления с использованием Parsley Framework, и в WPF я понимаю, что модель представления была изменена на шаблон MVVM.

Команда

Команда в [C] отличается от команды в MVVM, команда в [C] больше удовлетворяет как Шаблон команды, где в [C] контроллер действует как Invoker, поэтому в [C] команда фактически может поддерживать цепочку, отмену, транзакцию и т. д. В MVVM команда далека от шаблона команды. Основная идея использования Command в MVVM, потому что ICommand — единственный способ выполнить привязку к операции. Во Flex вы легко привязываете метод к событию, используя click="{viewmodel.doOperation()}", но не в WPF.

Model Locator

Сосредоточение состояния вашего приложения в одном Model Locator, как это сделал [C], является плохой практикой. С другой стороны, вы потеряете возможность «легко» протестировать свой код, если сделаете это. Чем более зависим ваш код, тем сложнее его тестировать, если ваш локатор модели содержит множество моделей меньшего размера, чем вы уже сильно зависите от своего кода. И самое страшное в использовании синглтона — это то, что над ним невозможно издеваться. поэтому, если ваш локатор модели не подходит для модульного тестирования, ваш процесс модульного тестирования может быть полон боли.

на самом деле не существует лучших практик, используемых в контексте MVVM для общей модели между представлениями, как вы упомянули, но вам следует взглянуть на термин внедрение зависимостей, чтобы добиться этого.

С наилучшими пожеланиями

1
ответ дан 5 December 2019 в 21:18
поделиться

Люди, обсуждающие MVVM, сделали его слишком теоретическим, а flex имеет действительно другую архитектуру, что делает MVVM немного сложным для людей, пришедших из flex.

Позвольте мне привести очень простой пример.

В Flex мы в основном создаем один MXML для компонента пользовательского интерфейса, и у нас есть наша привязываемая модель, и мы в основном пишем наш код в событиях компонента пользовательского интерфейса, а также в других компонентах пользовательского интерфейса. . Например, WebService, HttpService и т. д., они не являются компонентами пользовательского интерфейса, но они все же могут быть внутри MXML, и к ним можно легко получить доступ в коде MXML.

Таким образом, вы можете очень легко организовать Модель + Представление + Контроллер в одном файле MXML.

В Silverlight в XAML элементы пользовательского интерфейса могут быть только дочерними элементами изменяемой страницы или пользовательского элемента управления. Существуют ограничения, XAML позволяет размещать элементы, не относящиеся к пользовательскому интерфейсу, только в ресурсах, а типизированная переменная добавленного вами ресурса не так легко доступна в коде, стоящем за XAML, вам необходимо вызвать find resource для доступа к коду.

Чтобы упростить задачу, MVVM заставляет вас определять разные файлы.

У вас есть один файл, который представляет собой вашу модель, например, Customer.cs.

У вас есть еще один файл, который представляет собой вашу ViewModel, которая в основном представляет собой комбинацию Model + Commands.И вы пишете свой код контроллера в событии Executed команды.

У вас есть еще один файл, это ваше представление, представление в основном привязывается ко всем свойствам модели представления, которые являются либо моделью, либо командами.

0
ответ дан 5 December 2019 в 21:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: