WPF-如何处理从MainWindow中的UserControl引发的事件并更新ViewModel
我试图在UserControl1中引发一个事件,但我不知道如何处理该事件以在主窗口中显示UserControl2 MainWindow.xamlWPF-如何处理从MainWindow中的UserControl引发的事件并更新ViewModel,wpf,Wpf,我试图在UserControl1中引发一个事件,但我不知道如何处理该事件以在主窗口中显示UserControl2 MainWindow.xaml <Window x:Class="WpfApp1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
<Window x:Class="WpfApp1.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:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:ViewModel1 />
</Window.DataContext>
<Window.Resources>
<DataTemplate x:Key="Template1" DataType="{x:Type local:ViewModel1}">
<local:UserControl1 />
</DataTemplate>
<DataTemplate x:Key="Template2" DataType="{x:Type local:ViewModel1}">
<local:UserControl2 />
</DataTemplate>
</Window.Resources>
<Grid>
<ContentControl Content="{Binding }">
<ContentControl.Style>
<Style TargetType="{x:Type ContentControl}">
<Setter Property="ContentTemplate" Value="{StaticResource Template1}" />
<Style.Triggers>
<DataTrigger Binding="{Binding UserControlId}" Value="2">
<Setter Property="ContentTemplate" Value="{StaticResource Template2}" />
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</Grid>
</Window>
UserControl1.xaml
<UserControl x:Class="WpfApp1.UserControl1"
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"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Label Content="User Control 1" />
<Button x:Name="btnNext" Content="Next" Click="btnNext_Click"></Button>
</Grid>
</UserControl>
UserControl2.xaml
<UserControl x:Class="WpfApp1.UserControl2"
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"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Label Content="User Control 2" />
</Grid>
</UserControl>
ViewModel1.cs
using System.ComponentModel;
namespace WpfApp1
{
public class ViewModel1 : INotifyPropertyChanged
{
public int UserControlId { get; set; }
public ViewModel1()
{
UserControlId = 2;
}
public event PropertyChangedEventHandler PropertyChanged;
}
}
using System.ComponentModel;
namespace WpfApp1
{
public class ViewModel1 : INotifyPropertyChanged
{
private int _userControlId;
public int UserControlId {
get { return _userControlId; }
set
{
_userControlId = value;
RaisePropertyChanged("UserControlId");
}
}
private void RaisePropertyChanged(string v = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(v));
}
public ViewModel1()
{
UserControlId = 1;
}
public event PropertyChangedEventHandler PropertyChanged;
}
}
我想我必须更新ViewModel1中的UserControlId属性才能更改用户控件,但是在哪里处理以及如何让ViewModel1实例更改该属性
编辑1
很抱歉,ViewModel1构造函数中的输入错误,我的意思是将UserControlId属性初始化为1,而不是2
当我运行它时,我看到主窗口中加载了UserControl1的窗口。
UserControl1有一个按钮“下一步”。
单击UserControl1中的按钮,我想显示UserControl2。
所以我在button click事件处理程序中引发MyEvent routed事件。
现在,在哪里附加和编写MyEvent的事件处理程序,以及如何让ViewModel1实例更改其UserControlId属性?这里不需要路由事件。将ViewModel分配给MainWindow,并在MainViewModel中添加属性“UserControlId”。然后,当您在主窗口的DataContext级别上对UserControlId的值编写触发器时,XAML代码将正常工作。为此,您需要在两个视图模型之间进行调解。调解的一种方法是将主窗口作为调解器:它侦听来自子窗口的事件,然后将它们路由到所需的目的地。另一种方法是通过事件聚合器。大多数MVVM框架都有一个。据我所知,WPF世界中最好的开源软件是。在一个视图模型中订阅某种消息,然后从另一个视图模型发送事件,事件聚合器确保事件路由到其目标。有关更多详细信息,请参阅他们的文档。我终于实现了这一点。在ViewModel1中使用属性名称更改了引发的事件,在主窗口中添加了事件侦听器 这是更改的文件 ViewModel1.cs
using System.ComponentModel;
namespace WpfApp1
{
public class ViewModel1 : INotifyPropertyChanged
{
public int UserControlId { get; set; }
public ViewModel1()
{
UserControlId = 2;
}
public event PropertyChangedEventHandler PropertyChanged;
}
}
using System.ComponentModel;
namespace WpfApp1
{
public class ViewModel1 : INotifyPropertyChanged
{
private int _userControlId;
public int UserControlId {
get { return _userControlId; }
set
{
_userControlId = value;
RaisePropertyChanged("UserControlId");
}
}
private void RaisePropertyChanged(string v = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(v));
}
public ViewModel1()
{
UserControlId = 1;
}
public event PropertyChangedEventHandler PropertyChanged;
}
}
MainWindow.cs
using System.Windows;
namespace WpfApp1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
}
using System.Windows;
namespace WpfApp1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
AddHandler(UserControl1.MyEvent, new RoutedEventHandler(OnMyEvent));
}
private void OnMyEvent(object sender, RoutedEventArgs e)
{
var vm = (ViewModel1)DataContext;
vm.UserControlId = "2";
}
}
}
“将ViewModel分配给MainWindow”-我已经这样做了。触发器将更改UserControl,但如何触发它?从您提供的代码中,我可以看到属性“UserControlId”位于“ViewModel1”中,这就是DataTrigger无法获得正确的属性绑定的原因。它应该在MainViewModel中,在单击“下一步”按钮时也将属性的值更改为“2”。您可以使用caliburn.micro来执行此操作,查看“它侦听孩子们的事件,然后将其发送到他们所需的目的地。”-您能给我指一下可以执行此操作的资源吗?是的,我添加了链接。非常感谢您@smk