【问题标题】:Adding tabs to tabcontrol from inside a tab从选项卡内部将选项卡添加到选项卡控件
【发布时间】:2012-04-12 11:33:49
【问题描述】:

好吧,我已经有一段时间摸不着头脑了。但未能找到解决我的问题的方法。我拥有的是带有 ObservableCollection TabItems 的 MainViewModel。 MainViewModel 设置为 MainView(用户控件)的 DataContext,后者又托管 TabControl。 tabcontrol 绑定到 TabItems 集合。选项卡控件的内容将是 ReportItems 用户控件。

此设置主要用于报告 SSRS 的报告 UI。第一个选项卡包含一个报告列表,选择其中将显示一些列表框,用户可以从中选择报告参数。不是在选择参数后,用户点击一个按钮,然后生成一个报告并使用报告主机将一个选项卡添加到选项卡控件。

我试图从选项卡而不是主视图中选择报告的原因是有很多参数需要选择,如果我将列表框添加到主视图,留给选项卡控件的空间会更少并且用户需要向下滚动才能查看报告。

我不确定我的设计是否有缺陷,但我想找到一种方法将新的 ReportItemViewModel 添加到 TabItem 集合中。这意味着允许子选项卡通过将 ReportItemViewModel 对象发送到 MainViewModel 并添加到集合中来添加同级。

我曾想过使用静态 Collection 来执行此操作,但这不会调用我的 OnPropertyChange 方法。此外,在 MainViewModel 中使用静态方法也无济于事,因为它无法将对象添加到集合中,因为集合不是静态的。

我没有在这里发布任何代码,因为我被困在如何开始自己。我看了另一篇帖子here,但不知道怎么用。

对不起,描述太长了,只是想把问题说清楚。

如果我能得到更好的设计,我愿意接受任何建议。我很绝望,任何帮助将不胜感激。

【问题讨论】:

  • 您可以使用弹出窗口或扩展器来托管 UI 以进行添加过程。这样你就不会使用屏幕空间,也不会在你的 ReportItemViewModel 中编写添加逻辑。
  • Popup 是我想过的,但我觉得它看起来不合适。关于扩展器,由于我有多个报告,因此不确定如何实现它。您的意思是,对于每个报告,我都有一个处于禁用/不可见模式的扩展器,并且应该根据报告选择启用/可见。你能详细说明一下吗?
  • 您说您将列表放在选项卡中,而不是在主视图中,因为您想保留屏幕空间。我是说在主视图中使用扩展器可以在折叠时为您提供足够的空间来容纳报告,然后在展开时有足够的空间来添加新报告。
  • 嗯,我的理解是,您的建议是将参数列表放在主视图中,将 tabcontrol(带有选项卡中的报告)放在扩展器中?如果这是您的建议,它看起来可行,但我不确定它会给应用程序带来的外观和感觉。不过,会尝试,因为我现在除了这两个之外没有更多的想法。
  • 我的另一个建议正是雷切尔在她的回答中推荐的。看来您需要找到一种在 ViewModel(ReportItemViewModel 和 MainViewModel)之间进行通信的方法。您在 ReportItemViewModel 中创建项目并向 MainViewModel 发送一条消息,其中包含要添加到集合中的新添加项目。我过去成功地使用了事件聚合器模式来实现这一点。

标签: wpf mvvm .net-4.0


【解决方案1】:

ICommand 添加到您的MainViewModel 以将新项目添加到您的ObservableCollection,并使用RelativeSource 绑定从TabItem 中查找命令

所以你的 MainViewModel 会有

ObservableCollection<IViewModel> TabItems
IViewModel SelectedTabItem
ICommand AddTabCommand

AddTabCommand 基本上在哪里

void AddTab(IViewModel newItem)
{
    TabItems.Add(newItem);
    SelectedTabItem = newItem;
}

你的用户界面会看起来像这样

<DataTemplate DataType="{x:Type local:SelectReportViewModel}">
    <Grid>
        ...
        <!-- Use the CommandParameter property to pass specified ReportItemViewModel to open -->
        <Button Command="{Binding DataContext.AddTabCommand, 
                RelativeSource={RelativeSource AncestorType={x:Type TabControl}}}" />
        ...
    </Grid>
</DataTemplate>

<TabControl ItemsSource="{Binding TabItems}" />

另一种选择是使用某种事件系统,例如 MVVM Light 的 Messenger 或 Microsoft Prism 的 EventAggregator,来广播/订阅事件。

您的MainViewModel 将订阅AddTabEvents,而您的SelectReportViewModel 将在需要添加新标签时广播这些事件。如果您有兴趣,我在我的博客文章中有一个关于communication between ViewModels 的简短摘要。

【讨论】:

  • 这看起来很有希望。我实际上一直在寻找这样的东西,但从未听说过它,因为我对 WPF 相对较新。从来没有想过如何从一个虚拟机到另一个虚拟机进行通信。将实施并让您知道进展如何。
  • 太棒了......它工作......我使用了事件聚合器模式......工作就像一个魅力......非常感谢...... :)
猜你喜欢
  • 1970-01-01
  • 2011-05-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多