1

内容演示者

在上图中,child 是 ContentPresenter。它的内容是一个 ViewModel。但是,它的 ContentTemplate 为空。

在我的 XAML 中,我有一个 TabControl 具有以下结构:

<local:SuperTabControlEx DataContext="{Binding WorkSpaceListViewModel}"
 x:Name="superTabControl1" CloseButtonVisibility="Visible" TabStyle="OneNote2007" ClipToBounds="False" ContentInnerBorderBrush="Red" FontSize="24" >
            <local:SuperTabControlEx.ItemsSource>
                <Binding Path="WorkSpaceViewModels" />
            </local:SuperTabControlEx.ItemsSource>

                <TabControl.Template>
                <ControlTemplate
                    TargetType="TabControl">
                        <DockPanel>
                            <TabPanel
                            DockPanel.Dock="Top"
                            IsItemsHost="True" />
                            <Grid
                            DockPanel.Dock="Bottom"
                            x:Name="PART_ItemsHolder" />
                        </DockPanel>
                        <!-- no content presenter -->
                    </ControlTemplate>
                    </TabControl.Template>

            <TabControl.Resources>
            <DataTemplate DataType="{x:Type vm:WorkSpaceViewModel}">

            ....

WorkSpaceViewModels 是 WorkSpaceViewModel 的 ObservableCollection。此代码使用Keeping the WPF Tab Control from destroying its children中的代码和技术。

正确的 DataTemplate - 上面显示在 TabControl.Resource 中 - 似乎正在为两个选项卡呈现我的 ViewModel。

但是,我的基本问题是,我的视图如何连接到我的 WorkSpaceViewModel,然而,ContentPresenter 上的 ContentTemplate 为空?我的要求是从 ViewModel 访问可视组件,因为在某些用户操作后,视图的设置与 ViewModel 中的属性解除绑定,我需要重新绑定它。

4

2 回答 2

1

DataTemplate 是“隐式”定义的。ContentPresenter 将首先使用它的 ContentTemplate/Selector(如果已定义)。如果不是,那么它将搜索没有显式 x:Key 且其 DataType 与其 Content 类型匹配的 DataTemplate 资源。

这在此处此处进行了讨论。

视图模型不应该真正知道它的关联视图。听起来您的绑定有问题,因为通常您不必“重新绑定”它们。无论哪种方式,附加行为都是实现这一目标的好方法。

于 2011-04-22T00:10:20.950 回答
0

我认为这个问题的完整答案需要 DrWPF 的完整系列ItemsControl: A to Z。但是,我相信要点在于当 DataTemplate 被“膨胀”以显示框架链接到的数据项时,视觉元素的存储位置。

在“ItemsControl: 'L' is for Lookless”的控制模板介绍部分中,DrWPF 解释说:“我们已经了解到 DataTemplate 用于声明出现在应用程序逻辑树中的数据项的可视化表示。在“P”代表面板中,我们了解到 ItemsPanelTemplate 用于声明 ItemsControl 中使用的项目宿主。”

对于我的问题,我仍然没有成功导航可视化树以获得对我的拆分器项目的引用。这是我迄今为止最好的尝试:

// w1 is a Window
SuperTabControlEx stc = w1.FindName("superTabControl1") as SuperTabControlEx;
//SuperTabItem sti = (SuperTabItem)(stc.ItemContainerGenerator.ContainerFromItem(stc.Items.CurrentItem));

ContentPresenter myContentPresenter = FindVisualChild<ContentPresenter>(stc);
//ContentPresenter myContentPresenter = FindVisualChild<ContentPresenter>(sti);

DataTemplate myDataTemplate = myContentPresenter.ContentTemplate;

上面的代码是尝试实现msdn 网站上显示的技术。但是,当我将它应用到我的代码时,一切看起来都很好,除了 myDataTemplate 返回 null。如您所见,我在 SuperTabControlEx 和 SuperTabItem 上尝试了相同的技术,分别派生自 TabControl 和 TabItem。如我原来的帖子中所述,并且在 XAML 片段中很明显,SuperTabControlEx 还实现了Keeping the WPF Tab Control from destroying its children中的代码。

在这一点上,也许最重要的是,我认为这是一个导航可视树的练习。我将修改问题的标题以反映我对该问题的新概念。

于 2011-04-22T14:09:27.540 回答