Не могли бы вы более конкретно указать, на каких условиях?@ColineE и @ChrisBD правильно указывают на то, что ICommands и EventTocommandBehavior помогут во многих обстоятельствах, таких как преобразование события нажатия кнопки мыши или события наведения мыши в вызов метода в ViewModel. Я бы рекомендовал использовать эти подходы, если они могут быть использованы, поскольку они считаются наилучшей практикой
Однако в некоторых случаях требуется нечто более сложное, чем это.Одним из решений является использование кода для приведения DataContext к типу модели представления и непосредственного вызова метода.Например:
// Inside MyViewModel.cs
public class MyViewModel : INotifyPropertyChanged
{
// ...
}
// ...
// Inside MyControl.xaml.cs
public class MyControl : UserControl
{
public MyControl()
{
InitializeComponent();
}
pubilc void OnSomeConditionMatches()
{
var myViewModel = DataContext as MyViewModel;
if (myViewModel != null)
{
// Hacky, but it works
myViewModel.CallCustomMethod();
}
}
}
Это считается немного хакерским и загрязняет программный код знанием типа ViewModel во время выполнения.Что-то, чего мы хотим избежать, поскольку это нарушает разделение интересов между View и ViewModel.
Другой метод - это то, что я использовал сам, когда имел дело с пользовательским элементом управления, который почти не поддерживает привязку данных.Используя интерфейс для представления и присоединенное свойство, вы можете внедрить экземпляр представления в viewModel и манипулировать им напрямую .Вроде гибридного паттерна MVVM / MVP, который я придумал MiVVM.
UML
![MiVVM UML Diagram](https://i.stack.imgur.com/yG9LW.png)
Xaml:
<!-- Assumes myViewModel is the viewmodel we are binding to -->
<!-- which has property InjectedUserControl of type IMyControl -->
<Example3:MyControl DataContext="{StaticResource myViewModel}"
Injector.InjectThisInto="InjectedUserControl">
</Example3:MyControl>
Код:
// Defines an interface to the usercontrol to
// manipulate directly from ViewModel
public interface IMyControl
{
// Our test method to call
void CallView(string message);
}
// Defines the usercontrol
public partial class MyControl : UserControl, IMyControl
{
public MyControl()
{
InitializeComponent();
}
public void CallView(string message)
{
MessageBox.Show(message);
}
}
public class MyViewModel
{
private IMyControl myControl;
public IMyControl InjectedUserControl
{
set
{
Debug.WriteLine(string.Format("Received Injected Control \"{0}\"",
value == null ? "NULL" : value.GetType().Name));
this.myControl = value;
this.OnInjectedObjectsChanged();
}
}
private void OnInjectedObjectsChanged()
{
// Directly access the view via its interface
if (this.myControl != null)
this.myControl.CallView("Hello From MyViewModel");
}
}
Чтобы загрузить демоверсию, включающую источник присоединенного свойства Injector, см. этот блог запись.Также этот предыдущий вопрос , который связан.
С уважением,