wpf - 使用 MVVM 在另一个控件中执行方法
问题描述
我已经建立了一个假人UserControl
,它的代码隐藏中有一个方法来显示一条消息!我在我的主窗口中使用了这个控件,并希望在我单击Button
使用命令和 MVVM 时执行它的方法。我怎样才能做到这一点?
<UserControl x:Class="ControlBining.Control1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid DataContext="{Binding RelativeSource={RelativeSource AncestorType=UserControl}}">
</Grid>
</UserControl>
C#:
public partial class Control1 : UserControl
{
public Control1()
{
InitializeComponent();
}
public void ShowMessage()
{
MessageBox.Show("Called from other control!");
}
}
主窗口 XAML:
<Window x:Class="ControlBining.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ControlBining"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.DataContext>
<local:ViewModel/>
</Window.DataContext>
<StackPanel Margin="0 50 0 0">
<local:Control1 Width="100"/>
<Button Width="100" Content="Show Message"/>
</StackPanel>
</Window>
中继命令:
public class RelayCommand : ICommand
{
private readonly Predicate<object> m_canExecute;
private readonly Action<object> m_execute;
public RelayCommand(Predicate<object> canExecute, Action<object> execute)
{
m_canExecute = canExecute;
m_execute = execute;
}
public event EventHandler CanExecuteChanged
{
add => CommandManager.RequerySuggested += value;
remove => CommandManager.RequerySuggested -= value;
}
public bool CanExecute(object parameter)
{
return m_canExecute(parameter);
}
public void Execute(object parameter)
{
m_execute(parameter);
}
}
目前,我已经让它工作了,但我真的不确定它是否是一个好的设计:
控制代码隐藏
private void Control1_Loaded(object sender, RoutedEventArgs e)
{
ViewModel m = (ViewModel)DataContext;
m.ShowMessage += M_ShowMessage;
}
private void M_ShowMessage()
{
ShowMessage();
}
在视图模型中
public event Action ShowMessage;
private ICommand m_showMessageCommand;
public ICommand ShowMessageCommand
{
get
{
return m_showMessageCommand ?? (m_showMessageCommand = new RelayCommand(
p => true,
p => ShowMessage?.Invoke()));
}
}
XAML:
解决方案
如果您只需要显示一条消息,则应该将该ShowMessage()
方法移至视图模型并使用消息服务从视图模型类中执行此操作。
如果你真的想调用一些只在视图中定义才有意义的方法,这可以通过在视图中实现一个接口并用这个接口注入视图模型来完成。例如,当您调用命令时:
public interface IView
{
void ShowMessage();
}
public partial class Control1 : UserControl, IView
{
public Control1()
{
InitializeComponent();
}
public void ShowMessage()
{
MessageBox.Show("Called from other control!");
}
}
查看型号:
public ICommand ShowMessageCommand
{
get
{
return m_showMessageCommand ?? (m_showMessageCommand = new RelayCommand(
p => true,
p =>
{
IView view as IView;
if (view != null)
{
//...
view.ShowMessage();
}
}));
}
}
视图模型对视图一无所知,它只知道一个接口,当然可以称为IView
.
另一种选择是使用事件聚合器或信使以糟糕耦合的方式将事件或消息从视图模型发送到视图。有关这方面的更多信息,请参阅此博客文章。
这两种方法都没有打破 MVVM 模式。
推荐阅读
- javascript - 在 javascript window.open 中打印由 post 调用创建的 PDF 文件
- reactjs - 找不到功能实现React js
- typescript - 如何从键而不是值推断类型参数?
- android - Android用意图填充谷歌日历附件字段
- python - 如何使用值更新 many2many 列表 [ODOO 12]
- android - 取货地点预测列表
- python - 当我使用 input() 要求用户输入时,为什么会出现 NameError?
- javascript - 如何在节点 js 中将 TCP 套接字数据包发送到网页
- julia - 在 Julia 中解决 DDE 的问题
- python - 如何在 Pandas 中将具有 Null 值的浮点数据类型转换为整数?