Вызов метода в CodeBehind View из ViewModel? - PullRequest
19 голосов
/ 28 декабря 2011

У меня есть метод в коде позади моего View (этот метод что-то делает с моим пользовательским интерфейсом).

В любом случае, я бы хотел вызвать этот метод из моей ViewModel. Как это можно сделать?

Ответы [ 5 ]

22 голосов
/ 25 сентября 2014

Моя (а может и другие?) Проблема с MVVM заключалась в том, чтобы понять простую вещь: View знает о ViewModel .Я использовал привязки и команды, но они просты strings в xaml.Из-за безопасного разрешения во время выполнения (безопасный означает, что вы можете выполнить опечатку, но программное обеспечение не будет аварийно завершаться), это делает представление отделенным от модели представления (по крайней мере, во время компиляции).И я всегда искал решение, чтобы сохранить эту развязку, например, поведения.

Правда, вы можете получить доступ непосредственно к модели просмотра, которая обычно является DataContext оконного / пользовательского управления:

var vm = (MyViewModel)this.DataContext;

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

// define in the view model
public delegate void MyEventAction(string someParameter, ...);
public event MyEventAction MyEvent;

// rise event when you need to
MyEvent?.Invoke("123", ...);

// in the view
var vm = (MyViewModel)DataContext;
vm.MyEvent += (someParameter, ...) => ... // do something
2 голосов
/ 31 июля 2015

Вы можете сделать это следующим образом в View (код позади).

Он приводит к интерфейсу, который будет реализован ViewModel, так что вы не ограничены одним конкретным типом ViewModel.

    // CONSTRUCTOR
    public SomeView()
    {
        InitializeComponent();

        DataContextChanged += DataContextChangedHandler;
    }

    void DataContextChangedHandler(object sender, DependencyPropertyChangedEventArgs e)
    {
        var viewModel = e.NewValue as IInterfaceToBeImplementedByViewModel;

        if (viewModel != null)
        {
            viewModel.SomeEvent += (sender, args) => { someMethod(); }
        }
    }
2 голосов
/ 28 декабря 2011

Согласно шаблону MVVM ViewModel не знает о View, поэтому это недопустимо. Для взаимодействия с ViewModel View можно вызвать команду, также вы можете использовать привязки. Более того, вы не должны перемещать специфичные для пользовательского интерфейса вещи, такие как BusyIndicator, на уровень ViewModel.

Пожалуйста, предоставьте более подробную информацию о вашем конкретном случае использования - когда вы хотите вызвать метод View и что этот метод делает.

0 голосов
/ 28 декабря 2011

Вы можете написать класс действия, который принимает объект Data Transfer.В DTO добавьте свойство с именем «View» и назначьте ему текущее представление.Вызовите действие через контроллер из кодовой области вашего представления, распакуйте DTO, и теперь у вас есть полный контроль над представлением в классе действия.

Если вы действительно хотите сделать это в своей модели, просто создайте методс параметром типа «Вид» в вашей модели и выполнить его, передав текущий вид.

0 голосов
/ 28 декабря 2011

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

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

Итак, по вашему мнению, вы бы вызвали метод из ViewModel, чтобы начать читать набор данных, я прав??В этом методе вы можете передать делегат (указывающий на метод, который существует в вашем представлении), и когда ваша ViewModel закончит чтение набора данных с сервера, запустите делегат (из вашей модели представления), который связан с вашим методом в вашем представлении, чтоможет остановить индикатор занятости.

, так что, по вашему мнению, у вас есть

void StopBusyIndicator()
{
    this.BusyIndicator.IsBusy = false;
}

, и когда вы вызываете ViewModel для чтения набора данных,

вызывает его так:

ViewModel.ReadDataSet( ()= >StopBusyIndicator)

, который передаст метод StopBusyIndicator в качестве делегата, который можно вызвать в конце вашего ReadDataSet.

HTH

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...