如何在WPF/C#中创建可制表内容?

7
我在我的WPF应用程序中有一个TabControl。我想让我的应用程序基本上支持单个程序中的多个“实例”。例如,考虑Web浏览器,它们允许您在不同的选项卡中拥有多个网站的实例,我想实现类似的功能,其中我的应用程序包含几个“子应用程序”的实例。
我目前面临的问题是,我必须将相同的XAML复制粘贴到每个选项卡中,因为每个选项卡具有完全相同的标记和UI,但数据不同。另一个问题是,我需要动态创建那些选项卡的功能。
这是我的应用程序目前状态的屏幕截图。如您所见,顶部有2个选项卡,第二个具有透明背景,因为它处于非活动状态。
那么,我如何创建一个选项卡式系统,其中选项卡的UI对于每个选项卡保持相同,我只需要使用一个XAML UI进行开发,并将其复制到每个选项卡中?
要求:
- 每个选项卡具有相同的UI。 - 每个选项卡的UI元素有不同的数据。 - 作为开发人员,我希望仅在Visual Studio中为选项卡的XAML工作一次。
理想情况下,我希望有一个简单的示例项目/代码,其中有一个未经样式化的选项卡控件,并且在启动时应用程序会动态创建2-n个选项卡,这些选项卡都具有相同的UI,但是数据不同。
4个回答

3

如另一个回答中所述,可能有很多方法可以做到这一点,但这是我简单的方法:

定义一个DataTemplate,定义每个相同选项卡的内容。数据模板中的控件将绑定到当前选定选项卡的视图模型。在我的示例中,我放了一个TextBlock,但您可以轻松扩展它。

使用此Xaml:

<Page.DataContext>
    <Samples:TabBindingViewModels />
</Page.DataContext>

<Grid>
    <Grid.Resources>
        <DataTemplate x:Key="ContentTemplate" 
                      DataType="{x:Type Samples:TabBindingViewModel}">
            <TextBlock Text="{Binding Content}"/>
        </DataTemplate>
    </Grid.Resources>
    <TabControl ContentTemplate="{StaticResource ContentTemplate}"  
                DisplayMemberPath="Header" ItemsSource="{Binding Items}" />
</Grid>

并且这是视图模型的代码:

public class TabBindingViewModels
{
    public TabBindingViewModels()
    {
        Items = new ObservableCollection<TabBindingViewModel>
                    {
                        new TabBindingViewModel(1),
                        new TabBindingViewModel(2),
                        new TabBindingViewModel(3),
                    };
    }

    public IEnumerable<TabBindingViewModel> Items { get; private set; }
}

public class TabBindingViewModel
{
    public TabBindingViewModel() : this(0)
    {
    }

    public TabBindingViewModel(int n)
    {
        Header = "I'm the header: " + n.ToString(CultureInfo.InvariantCulture);
        Content = "I'm the content: " + n.ToString(CultureInfo.InvariantCulture);
    }

    public string Header { get; set; }
    public string Content { get; set; }
}

我们得到:
我们非常喜欢这篇关于如何样式化标签控件的教程,您可以轻松地将更加复杂的内容放入标签头部和内容中。
您应该仔细研究标签控件的完整模板以深入了解其工作原理。可以使用Blend或VS11 beta提取模板。
为了动态添加/删除标签页,现在您只需要向视图模型的ObservableCollection中添加/删除项即可。

2
这实际上可能会变成一个相当大的答案,因为有许多不同的路径可以选择。
重要的是要理解TabControl是一个ItemsControl,这意味着它可以包含一组对象,例如UserControls,每个模块都由它们组成。因此,您可以从将Items属性绑定到某些UserControl对象的ObservableCollection{T}开始,这些对象位于实现了类似于Prism中IModule的接口的某个模块项目内。该接口定义了可以在选项卡中加载的任何模块的起点。随着模块的请求,您只需加载程序集并添加一个选项卡,其中包含对模块中定义的区域的引用。
实际上并不是很难,但我建议你阅读有关 Prism 的资料,因为它可以为你处理大部分繁重的工作。最近,我刚刚使用Prism构建了一个与你描述的界面完全相同的接口。

有趣,我甚至都不知道Prism。 - Tower
有一些示例演示应用程序我可以看看吗? - Tower
1
很遗憾,我不知道有没有任何开源的应用程序。这里的快速入门指南可能会帮助您入门。如果您遇到困难,请随时提出新问题。;-) 一旦您开始使用,我保证它并不太难。http://msdn.microsoft.com/en-us/library/ff921153(v=pandp.40).aspx#sec15 - senfo
凭借您以往的专业知识,您是否可以编写一个简单的应用程序,其中包含一个选项卡控件,在应用程序启动时创建2个或更多选项卡项目,它们都具有相同的用户界面但包含不同的数据?我相信我不是唯一在寻找这种解决方案的人,这个示例代码/项目将受益于许多人。 - Tower

1

可以看看 Caliburn.Micro,它是基于 MVVM 框架的一种解决方案。你所问的确切问题已经在其中一个示例解决方案中得到了解决。

http://caliburnmicro.codeplex.com/


它有一些要求吗?我尝试在VS 2011中打开许多示例,其中大部分都抱怨缺少程序集,我甚至通过手动添加我从Silverlight bin文件夹中找到的程序集来修复了其中一些,但它仍然会抱怨,例如“属性'Dock'在XML命名空间'clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Toolkit'中的类型'StackPanel'上不存在”。您还记得哪个示例确切地回答了我的问题---然后我可以继续尝试修复那个特定的示例 :) - Tower
@rFactor,示例的名称是 Caliburn.Micro.SimpleMDI。它是样本列表中为数不多的非 Silverlight 项目之一。我仍然使用 VS 2010,在其中加载和运行该项目没有问题。 - code4life
我猜你在解压缩之前没有解除zip文件的阻止。右键单击zip文件并选择属性。点击“解除阻止”按钮。现在解压缩它。你可能会发现事情变得更好了。 - Phil

1

没有更多的信息,我的方法是在每个实例或选项卡的ApplicationDomain中启动一个MVVM提供程序。当您关闭选项卡时,卸载应用程序域。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接