Как вы перемещаетесь по сложному дереву визуалов, чтобы повторно связать существующий элемент? - PullRequest
1 голос
/ 21 апреля 2011

ContentPresenter

На изображении выше, child является ContentPresenter. Его содержимое является ViewModel. Однако его ContentTemplate имеет значение null.

В моем 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 - это ObservableCollection of WorkSpaceViewModel. Этот код использует код и технику из Предохранение элемента управления вкладки WPF от уничтожения его дочерних элементов .

Правильный DataTemplate - показанный выше в TabControl.Resource - похоже, отображает мою ViewModel для двух вкладок.

Тем не менее, мой основной вопрос: как мое представление подключается к моей WorkSpaceViewModel, но ContentTemplate в ContentPresenter имеет значение null? Мое требование состоит в том, чтобы получить доступ к визуальному компоненту из ViewModel, поскольку настройка для представления становится несвязанной с его свойством в ViewModel при определенных действиях пользователя, и мне нужно повторно привязать его.

Ответы [ 2 ]

1 голос
/ 22 апреля 2011

DataTemplate определяется «неявно».ContentPresenter сначала будет использовать свой ContentTemplate / Selector, если таковой определен.Если нет, то он будет искать ресурс DataTemplate без явного ключа x: Key, тип данных которого соответствует типу его содержимого.

Это обсуждается здесь и здесь .

Модель представления на самом деле не должна знать о своем связанном представлении.Похоже, что с вашими привязками что-то не так, так как в общем случае вам не нужно «привязывать» их.В любом случае, прикрепленное поведение было бы хорошим способом сделать это.

0 голосов
/ 22 апреля 2011

Я думаю, что полный ответ на этот вопрос влечет за собой полную серию DrWPF ItemsControl: от A до Z .Тем не менее, я полагаю, что суть заключается в том, где визуальные элементы хранятся, когда DataTemplate «раздувается» для отображения элемента данных, с которым он был связан платформой.

В разделе Введение в шаблоны управления в "ItemsControl: 'L' для Lookless" 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;

Приведенный выше код является попыткой реализовать методы, показанные на веб-сайте msdn .Однако, когда я применяю его к своему коду, все выглядит хорошо, за исключением того, что myDataTemplate возвращается null.Как вы можете видеть, я попробовал ту же технику на SuperTabControlEx и SuperTabItem, полученных из TabControl и TabItem, соответственно.Как описано в моем первоначальном посте и очевидно из фрагмента XAML, SuperTabControlEx также реализует код из Сохранение элемента управления вкладки WPF от уничтожения его дочерних элементов .

На данный момент, возможно, более всегоиначе, я думаю, что это упражнение в навигации по дереву визуалов.Я собираюсь изменить название вопроса, чтобы отразить мои новые концепции проблемы.

...