如何导航复杂的Visual Tree以重新绑定现有元素?

时间:2011-04-21 17:24:59

标签: wpf mvvm tabcontrol contentpresenter

ContentPresenter

在上图中,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中的代码和技术。

上面显示的TabControl.Resource中的正确DataTemplate似乎是为两个Tabs呈现我的ViewModel。

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

2 个答案:

答案 0 :(得分:1)

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

我们讨论了herehere

View Model不应该真正了解它的相关View。听起来你的Bindings有问题,因为一般来说你不应该“重新绑定”它们。无论哪种方式,attached behavior都是实现这一目标的好方法。

答案 1 :(得分:0)

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

在“ItemsControl:'L'用于Lookless”的Introduction to Control Templates部分中,DrWPF解释说“我们已经知道DataTemplate用于声明出现在数据项中的数据项的可视化表示。应用程序的逻辑树。在'P'用于Panel时,我们了解到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;

上述代码试图实现on the msdn web site所示的技术。但是,当我将它应用于我的代码时,一切看起来都不错,除了myDataTemplate返回null。如您所见,我在SuperTabControlEx和SuperTabItem上尝试了相同的技术,分别派生自TabControl和TabItem。正如我在原始帖子中所描述的那样,在XAML片段中,SuperTabControlEx也实现了Keeping the WPF Tab Control from destroying its children的代码。

此时,或许最重要的是,我认为这是导航Visual Tree的练习。我将修改问题的标题,以反映我对该问题的新概念。