Подтвердить что ты не робот

Вызов метода в представлении CodeBehind из ViewModel?

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

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

4b9b3361

Ответ 1

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

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

var vm = (MyViewModel)this.DataContext;

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

// 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

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

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

Ответ 3

Вы можете сделать это в виде (код позади).

Он обращается к интерфейсу, который будет реализован 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(); }
        }
    }

Ответ 4

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

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

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

поэтому, на ваш взгляд, у вас есть

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

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

назовите его следующим образом:

ViewModel.ReadDataSet( ()= >StopBusyIndicator)

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

HTH

Ответ 5

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

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