我正在尝试在UserControl1中引发一个事件,但我无法弄清楚如何处理该事件以在MainWindow中显示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"
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>
MainWindow.cs
using System.Windows;
namespace WpfApp1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
}
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>
UserControl1.cs
using System.Windows;
using System.Windows.Controls;
namespace WpfApp1
{
public partial class UserControl1 : UserControl
{
public static readonly RoutedEvent MyEvent = EventManager.RegisterRoutedEvent(
"MyEventName",
RoutingStrategy.Bubble,
typeof(RoutedEventHandler),
typeof(UserControl1)
);
public event RoutedEventHandler LoginEventHandler
{
add { AddHandler(MyEvent, value); }
remove { RemoveHandler(MyEvent, value); }
}
public UserControl1()
{
InitializeComponent();
}
private void btnNext_Click(object sender, RoutedEventArgs e)
{
var eventArgs = new RoutedEventArgs(MyEvent);
RaiseEvent(eventArgs);
}
}
}
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>
UserControl2.cs
using System.Windows.Controls;
namespace WpfApp1
{
public partial class UserControl2 : UserControl
{
public UserControl2()
{
InitializeComponent();
}
}
}
ViewModel1.cs
using System.ComponentModel;
namespace WpfApp1
{
public class ViewModel1 : INotifyPropertyChanged
{
public int UserControlId { get; set; }
public ViewModel1()
{
UserControlId = 2;
}
public event PropertyChangedEventHandler PropertyChanged;
}
}
我认为我必须更新ViewModel1中的UserControlId属性来更改用户控件但是在哪里处理以及如何让ViewModel1实例更改属性?
编辑1 对于ViewModel1构造函数中的拼写错误,我打算将UserControlId属性初始化为1,而不是2。
当我运行它时,我看到主窗口中加载了UserControl1的窗口。 UserControl1有一个按钮“下一步”。 单击UserControl1中的按钮,我想显示UserControl2。 所以我在按钮点击事件处理程序中提升MyEvent路由事件。 现在,在哪里附加和编写MyEvent的事件处理程序以及如何让ViewModel1实例更改它的UserControlId属性?
答案 0 :(得分:1)
我终于开始工作了。在ViewModel1中使用属性名称更改了引发的事件,在MainWindow中添加了事件侦听器,
以下是更改的文件
ViewModel1.cs
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();
AddHandler(UserControl1.MyEvent, new RoutedEventHandler(OnMyEvent));
}
private void OnMyEvent(object sender, RoutedEventArgs e)
{
var vm = (ViewModel1)DataContext;
vm.UserControlId = "2";
}
}
}
答案 1 :(得分:0)
不要以为这里需要路由事件。将ViewModel分配给MainWindow并添加Property&#34; UserControlId&#34;在MainViewModel中。然后,当您在MainWindow的DataContext级别上编写UserControlId值的触发器时,您的XAML代码将正常工作。
答案 2 :(得分:0)
为了做到这一点,你需要在两个视图模型之间进行调解。调解的一种方法是将主窗口作为调解器:它侦听来自子节点的事件,然后将它们路由到所需的目的地。另一种方式是通过事件聚合器。大多数MVVM框架都有一个。我在WPF世界中所知道的最好的开源是Caliburn Micro中的那个。您在一个视图模型中订阅了某种消息,然后从其他视图模型发送事件,事件聚合器确保事件被路由到其目标。有关详细信息,请参阅其文档。