2012-03-29 2 views
1

Я подталкиваю себя к тому, чтобы сделать приложения, которые я пишу проще, и я сделал несколько шагов, чтобы сделать это, но у меня осталась интересная проблема, которая совсем не чувствую, что это будет уникально для меня. Мне интересно, что я делаю неправильно.Упрощение ICommand/RelayCommand в подходе MVVM

У меня есть ViewModel, который хранит коллекцию объектов модели. Представление представляет собой ListView, который отображает все объекты в коллекции. Объекты модели имеют всю логику в них, чтобы манипулировать ими. Внутри строки ListView для каждого элемента у меня есть кнопка, и эта кнопка должна быть подключена для вызова метода на объекте модели.

Для того, чтобы это сработало, мне нужно добавить привязку команд, но в контекст данных родительского окна, который передает параметр объекта модели в строке, чтобы объект модели мог использоваться внутри ViewModel (родительского окна данных) для вызова метода на объект модели, который передается.

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

+0

Вы можете использовать привязку с RelativeSource, которая указывает родительское окно, а затем свойство DataContext.MyCommand. – Jeff

+0

Почему ваши модели не создают привязку команды, которая вызывается непосредственно кнопкой в ​​представлении модели? – Phil

+0

Я тоже думал об этом, но насколько я уверен, встраивание бизнес-логики в мои модели, используя части .NET-библиотек из System.Windows (DependencyObject - так что я мог бы привязываться) и System.Windows.Input (ICommand/RoutedCommand) просто кажется неправильным иметь в модельном объекте. – Andrew

ответ

0
{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, 
    Path=DataContext.MyCommand} 
+0

Это именно то, что я сделал бы, если бы я просто его реализовал, но мой вопрос заключается не в том, как это сделать, а в том, что это более простой способ, который не настолько тупой. – Andrew

+0

Вы можете написать расширение разметки, чтобы упростить выражение упомянутого связывания. – Jeff

+0

Я пытаюсь это прямо сейчас, но в идеале я хочу, чтобы расширение разметки имело возможность напрямую обращаться к объекту. Что-то по строкам: 'Command = {app: CustomExtension Object = CurrentObject, MethodName = MethodName}' Я изо всех сил пытаюсь заставить это работать. – Andrew

0

Создайте класс презентатора в вашей модели ViewModel для объектов модели и получите их коллекцию. Затем вы можете поместить свойство ICommand на них и передать ссылку на метод, который вы хотите вызвать в родительском datacontext.

Возможно, что-то вроде следующего:

public class ModelPresenter : INotifyPropertyChanged 
{ 
    private Model _model; 

    public ModelPresenter(Model model, Action<Model> parentAction) 
    { 
     _model = model 
     _action = parentAction; 
    } 

    public ICommand MyAction 
    { 
     get { return new RelayCommand(() => _parentAction(_model)); } 
    } 

    ... 
} 

Это также звучит, как вы могли бы быть обязательными к свойствам вашей модели вашей точки зрения. Вы не должны этого делать, поскольку это может вызвать утечку памяти, если ваши модели не реализуют INotifyPropertyChanged (см.: http://support.microsoft.com/kb/938416/en-us).

+0

Я привязываюсь непосредственно к модели, но я решил использовать INotifyPropertyChanged для всех моих элементов модели, чтобы сделать это. – Andrew

Смежные вопросы