WPF 用户控件嵌套控件 - 从 Usercontrol 切换 Usercontrol

WPF User Control nested control - switch Usercontrol from Usercontrol

我目前正在 Visual Studio 中使用 WPF 开发一个应用程序作为 MySQL 数据库的前端,然后应该在学校中使用它来组织硬件等.更容易一点。 我是 C# 和 WPF 的新手,因此现在 运行 遇到了一个我在过去几个小时内无法解决的问题。 UI 由带有 Navbar 等的 Window 和用于显示当前 UserControl 的大 Frame/Grid 组成。

单击主窗口导航栏中的按钮会触发一个事件,然后只需使用以下几行即可毫无问题地切换 UserControl:

ContentFrame.Children.Clear();  //ContentFrame is a simple Grid which I am using ot display the UserControls
ContentFrame.Children.Add(new UserControlDashboard());  //UserControlDashboard is the Class of one of my UserControls

我不知道这是否真的是最好的实现方式(因为它总是重新加载 UserControl),但至少它简单且有效。

问题是,我只能通过主窗口 Class 切换用户控件。但我希望能够从其中一个 UserControl 中切换 UserControl。 (例如,我的一个 UserControl 显示了一个数据网格,其中包含来自我的一个数据库 table 的所有数据。通过双击这些行之一,我希望能够将当前的 UserControl 切换为 table到另一个。)

但我真的不知道我该怎么做。我做了一些研究,但只找到了由许多不同的 类 和许多不同的事件处理程序等组成的解决方案,不幸的是我无法真正弄清楚该实现是如何工作的。并且它也被限制为 2 个 UserControls。

有什么方法可以在合理的时间内实现吗?我读过使用路由事件可以做到吗?因为我是 C# 的新手,所以我对事件、调度程序等完全陌生,因此很难处理所有基于事件的内容。 :D

谢谢 :)

一个简单的解决方案是使用数据绑定:

MainWindow.xaml

<Window>
  <StackPanel>
    <SwitchingControl x:Name="BindingSourceControl" />
    <ContentControl x:Name="ContentFrame" 
                    Content="{Binding ElementName=BindingSourceControl, Path=SelectedControl}" />
  </StackPanel>
</Window>

SwitchingControl.xaml.cs

partial class SwitchingControl : UserControl
{
  public static readonly DependencyProperty SelectedControlProperty = DependencyProperty.Register(
    "SelectedControl",
    typeof(Control),
    typeof(SwitchingControl),
    new PropertyMetadata(default(Control)));

  public Control SelectedControl
  {
    get => (Control) GetValue(SwitchingControl.SelectedControlProperty);
    set => SetValue(SwitchingControl.SelectedControlProperty, value);
  }

  // Dictionary to store reusable controls
  private Dictionary<string, Control> ControlMap { get; set; }

  public SwitchingControl()
  {
    this.ControlMap = new Dictionary<string, Control>() 
    { 
      { nameof(UserControlDashboard), new UserControlDashboard()) }
    };
  }

  // TODO::Invoke when a DataGrid row was double clicked
  private void OnNewControlSelected(string selectedControlKey)
  {
    if (this.ControlMap.TryGetValue(selectedControlKey, out Control selectedControl)
    {
      this.SelectedControl = selectedControl;
    }
  }
}

更高级的解决方案将涉及 DataTemplate 和不同的视图模型或数据模型,特定类型将映射到特定控件。然后显示控件,当添加模型时,例如到 ContentPresenter,它将自动应用正确的 DataTemplate 以可视化模型数据。