我构建了一个虚拟的UserControl
,它的代码隐藏中有一个显示消息的方法。我在主窗口中使用了这个控件,并希望在使用命令和MVVM单击Button
时执行它的方法。这是一个好的设计吗?如果不是,我该如何改进它?我当前的代码如下所示:
<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>
public partial class Control1 : UserControl
{
public Control1()
{
InitializeComponent();
}
public void ShowMessage()
{
MessageBox.Show("Called from other control!");
}
}
<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()));
}
}
1条答案
按热度按时间wwwo4jvm1#
如果只需要显示一条消息,则应该将
ShowMessage()
方法移到视图模型中,并使用消息服务从视图模型类中完成此操作。如果你真的想调用某个只有在视图中定义才有意义的方法,可以通过在视图中实现一个接口,并将这个接口注入视图模型来实现,例如当你调用命令时:
查看型号:
视图模型对视图一无所知,它只知道一个接口,这个接口当然可以被称为
IView
以外的其他名称。另一种选择是使用事件聚合器或消息发送器,以一种松散耦合的方式将事件或消息从视图模型发送到视图,请参考this博客文章了解更多信息。
这两种方法都没有打破MVVM模式。