powered by simpleCommunicator - 2.0.50     © 2025 Programmizd 02
Форумы / WPF, Silverlight [игнор отключен] [закрыт для гостей] / Переключение между Tab'ами лагает
13 сообщений из 13, страница 1 из 1
Переключение между Tab'ами лагает
    #38712577
Фотография _Novichok
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
есть TabControl. К нему как источник Tab'ов биндится коллекция навигаторов, которые могут быть нескольких типов, объединенных
одним базовым классом.
TabControl
Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
<TabControl x:Name="TabControl"
            Style="{StaticResource TabControlStyle}"
            ItemsSource="{Binding Navigators}">
    <TabControl.Resources>
       
        <DataTemplate DataType="{x:Type vms:NavigatorViewModel}">
            <TextBlock Text="{Binding RootNodeHeader}"/>
        </DataTemplate>     
    </TabControl.Resources>
    
    <TabControl.ContentTemplateSelector>
        <ts:TabContentTemplateSelector 
            PersonsTreeDataTemplate="{StaticResource PersonsNavigatorTemplate}"
            ProjectsTreeDataTemplate="{StaticResource ProjectsNavigatorTemplate}"/>
    </TabControl.ContentTemplateSelector>
</TabControl>


стиль для TabControl'а. В нем переопределяется темплейт с включением кнопки для добавления новых навигаторов.
TabControlStyle
Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
<Style x:Key="TabControlStyle" TargetType="{x:Type TabControl}">
    <Setter Property="OverridesDefaultStyle" 
            Value="True"/>
    <Setter Property="SnapsToDevicePixels" 
            Value="True"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type TabControl}">
                <Grid KeyboardNavigation.TabNavigation="Local">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition x:Name="ColumnDefinition0"/>
                        <ColumnDefinition x:Name="ColumnDefinition1" 
                                          Width="Auto"/>
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="*"/>
                    </Grid.RowDefinitions>

                    <TabPanel x:Name="HeaderPanel"
                              Grid.Row="0"
                              Panel.ZIndex="1"
                              Margin="2,2,2,0"
                              IsItemsHost="True"
                              KeyboardNavigation.TabIndex="1"
                              Background="Transparent"/>
                    <customControls:DropDownButton Grid.Row="0" 
                                       Grid.Column="1" 
                                       Style="{StaticResource ToogleButtonStyle}" >

                        <StackPanel Orientation="Horizontal" >
                            <TextBlock Text="Add..."/>                            
                            <Separator Width="14" 
                                       Margin="4,0,0,0">
                                <Separator.LayoutTransform>
                                    <RotateTransform Angle="90"/>
                                </Separator.LayoutTransform>
                            </Separator>
                            <TextBlock Text="&#9660;" 
                                       VerticalAlignment="Center" 
                                       Margin="2,0,2,0"/>
                        </StackPanel>
                        <customControls:DropDownButton.DropDown>
                            <ContextMenu>
                                <MenuItem Name="NewProjectNavigatorMenuItem"
                                          Header="New Projects Navigator..."
                                          Command="{Binding NewProjectsNavigatorCommand}"/>
                                <MenuItem Name="NewPersonNavigatorMenuItem"
                                          Header="New Persons Navigator..."
                                          Command="{Binding NewPersonsNavigatorCommand}"/>
                            </ContextMenu>
                        </customControls:DropDownButton.DropDown>
                    </customControls:DropDownButton>

                    <Border Name="ContentPanel"
                            Grid.Column="0"
                            Grid.ColumnSpan="2"
                            Grid.Row="1"
                            Background="{StaticResource WindowBackgroundBrush}"
                            BorderBrush="{StaticResource SolidBorderBrush}"
                            BorderThickness="1"
                            CornerRadius="0,0,7.5,7.5"
                            KeyboardNavigation.TabNavigation="Local"
                            KeyboardNavigation.DirectionalNavigation="Contained"
                            KeyboardNavigation.TabIndex="2">

                        <ContentPresenter Name="PART_SelectedContentHost"
                                          Margin="0"
                                          ContentSource="SelectedContent">
                        </ContentPresenter>
                    </Border>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsEnabled" 
                             Value="False">
                        <Setter Property="Foreground" 
                                Value="{StaticResource DisabledForegroundBrush}"/>
                        <Setter TargetName="ContentPanel" 
                                Property="BorderBrush" Value="{StaticResource DisabledBorderBrush}"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>    
</Style>



Для каждого типа навигатора для контента вкладки описывается темплейт с деревом внутри.

Теперь суть проблемы: создаю несколько вкладок с разными типами. После переключения между вкладками то состояние, в каком было дерево теряется, то есть, те узлы дерева, которые были развернутые, сворачиваются обратно. И узлы дерева на вкладка принимают один и тот же вид (если это вкладки одинаковых типов).

Вопрос: в чем причина, где копать? Я так подозреваю, что проблема может быть темплейте для TabControla.
...
Рейтинг: 0 / 0
Переключение между Tab'ами лагает
    #38712692
Фотография @k@DElpher
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Novichok,

Пока все молчат. Что-то подсказывает, что проблема не в стиле для TabControl'а.
И лучше сначала проверять на минимально проекте. С WPF не работаю, но быстро собрал тестовый вариант с одной ViewModel, без селектора. Действительно при смене табов состояние теряется. А вот если два раза закинуть ссылку на одну ViewModel, то состояние "синхронизируется".

То есть проблема в потере состояния. Судя по всему, там ContentPresenter выкидывает состояние при смене SelectedContent (точнее каждый раз создает новое). С точки зрения MVVM это состояние должно храниться в твоей ViewModel. Тут правда тоже мороки, этот TreeView как-то не очень под MVVM заточен:

Там для биндинга выбранных элементов, развернутых элементов нужно использовать переопределение стиля TreeViewItem:

Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
<TreeView>
  <TreeView.ItemContainerStyle>
    <Style TargetType="TreeViewItem">
      <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/>
      <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}"/>
    </Style>
  </TreeView.ItemContainerStyle>
</TreeView>


Sourece: http://stackoverflow.com/questions/9143107/get-selected-treeviewitem-using-mvvm


В гугле поиск: tabcontrol lost state. А вот какое решение верней не знаю)

http://stackoverflow.com/questions/2238072/tabcontrol-disposes-of-controls-on-inactive-tabs
http://stackoverflow.com/questions/2080764/how-to-preserve-control-state-within-tab-items-in-a-tabcontrol
http://stackoverflow.com/questions/22336497/wpf-tabcontrol-tabs-losing-state-information


Про минимальный, вроде такого:
Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
   
<TabControl x:Name="tabControl">   
            <TabControl.ContentTemplate>
                <DataTemplate DataType="{x:Type vms:TabItemVM}">
                    <TreeView ItemsSource="{Binding children}">
                        <TreeView.ItemTemplate>
                            <HierarchicalDataTemplate ItemsSource="{Binding children}">
                                <TextBlock Text="{Binding name}"/>
                            </HierarchicalDataTemplate>
                        </TreeView.ItemTemplate>
                    </TreeView>
                </DataTemplate>
            </TabControl.ContentTemplate>
        </TabControl>




_NovichokИ узлы дерева на вкладка принимают один и тот же вид (если это вкладки одинаковых типов).

Под вопросом этот момент
...
Рейтинг: 0 / 0
Переключение между Tab'ами лагает
    #38712694
Фотография @k@DElpher
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_NovichokИ узлы дерева на вкладка принимают один и тот же вид (если это вкладки одинаковых типов).
Под вопросом этот момент. У меня такое вышло, не когда одинаковые типы, а когда объекты физически одинаковые (одного типа и ссылаются на один экземпляр)
...
Рейтинг: 0 / 0
Переключение между Tab'ами лагает
    #38712749
Фотография _Novichok
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
@k@DElpher_NovichokИ узлы дерева на вкладка принимают один и тот же вид (если это вкладки одинаковых типов).
Под вопросом этот момент. У меня такое вышло, не когда одинаковые типы, а когда объекты физически одинаковые (одного типа и ссылаются на один экземпляр)
ну тут не может быть одинаковых экземпляров, поскольку каждый таб - элемент колекции - это отдельный объект, который создается по нажатию кнопкии (с использованием ключевого слова new - насколько я знаю это влечет за собой создание нового экземпляра в памяти), то есть равенство объектов может быть исключено; все поля каждого объекта заполняются из базы данных.

опять же, я не могу предугадать все, что фреймворк должен делать сам, и выносить состояние элемента управления в ViewModel - это даже противоречит концепции MVVM (ViewModel не знает о View, тем более, что ViewModel и View у меня находятся в разных сборках). Когда я программировал на WinForms, то не заботился о таких вещах
...
Рейтинг: 0 / 0
Переключение между Tab'ами лагает
    #38712798
Фотография @k@DElpher
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Novichok,

скорее наоборот, View ничего не знает о ViewModel. А вот ViewModel специально снабжается всем, что может понадобиться для View (команды, состояния, SelectedItems и т.д.- всё, что отличает model от ViewModel)
---
Ну вот я у себя пробую, состояние копируется, если объекты дерева одного экземпляра. Если в деревьях разные экземпляры, но одинаковые внутренности (только внешне, то есть поля, текст, структура), то состояние не запоминается.
Может из базы в дерево попадают одинаковые экземпляры (ну там синглетон какой)?
Можно попробовать проверить оператором сравнения или в режиме отладки, добавив переменные с объектом в Watch List и нажав Make Object ID (разные экземпляры пометятся разными номерами)
...
Рейтинг: 0 / 0
Переключение между Tab'ами лагает
    #38712831
Фотография @k@DElpher
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я поясню, что это даже не из-за TabControl, а из-за того, что TabControl основан на ContentPresenter. При переключении вкладки его контент меняется и старый уходит для экономии памяти.
Бегло три решения:
Описаные тут ( http://stackoverflow.com/questions/2238072/tabcontrol-disposes-of-controls-on-inactive-tabs)
1) Самому хранить то, что нужно
2) Использовать UserControl на каждый таб
и вот третий:
3) http://stackoverflow.com/questions/9794151/stop-tabcontrol-from-recreating-its-children
Предлагают модифицировать TabControl. Вместо ContentPresenter там используют Grid в который запихиваются все табы, а при смене выбранного таба вместо его пересоздания меняется свойство Visibility
...
Рейтинг: 0 / 0
Переключение между Tab'ами лагает
    #38712851
Фотография _Novichok
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
@k@DElpherскорее наоборот, View ничего не знает о ViewModel.
Я с вами не согласен. ViewModel предоставляет свойтсва, команды, события для привязки их в View.
Соотвественно, ViewModel может использоватсья в разных местах View или в разных View (как собственно, у меня)
...
Рейтинг: 0 / 0
Переключение между Tab'ами лагает
    #38712865
Фотография _Novichok
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
@k@DElpherПредлагают модифицировать TabControl. Вместо ContentPresenter там используют Grid в который запихиваются все табы, а при смене выбранного таба вместо его пересоздания меняется свойство Visibility
Наверное, этот вариант будет наиболее приемлемым. Попробую. Спасибо
...
Рейтинг: 0 / 0
Переключение между Tab'ами лагает
    #38712881
Фотография @k@DElpher
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А, об это уже много костылей сломано). Но это дело вкуса.
При чем: @k@DElpherView ничего не знает о ViewModel в разных источниках по разному. Но тут с формулировкой вы правее). С другой стороны, как не крути, по факту, и представление и модель представления пишутся совместно. По научному раздельно, по факту вы за ранее знаете что вам во ViewModel нужен будет SelectedItem, если используется ListBox и IsSelected для каждого элемента, если используется дерево. Кто-то даже умудряется во ViewModel запихать свойства Visibility, потому что не хочется писать биндинги с конвертерами, а ведь можно так и так сделать. И в каждом случае нужно знать на что способен XAML и, что действительно потребуется от ViewModel.

С меня оффтоп).

В общем, не все там в WPF под MVVM заточено хорошо.
...
Рейтинг: 0 / 0
Переключение между Tab'ами лагает
    #38712892
Фотография @k@DElpher
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Novichok@k@DElpherПредлагают модифицировать TabControl. Вместо ContentPresenter там используют Grid в который запихиваются все табы, а при смене выбранного таба вместо его пересоздания меняется свойство Visibility
Наверное, этот вариант будет наиболее приемлемым. Попробую. Спасибо

Вы только пошарьте еще на тему. На stackoverflow не обязательно универсальное решение.
http://www.codeproject.com/Articles/212233/Persist-the-Visual-Tree-when-switching-tabs-in-the (Вот например, у этого в комментариях пишут про проблемы с TemplateSelector, но там же в комментариях описывают, как это обойти)
http://www.codeproject.com/Articles/362940/Persist-the-Visual-Tree-when-switching-tabs-in-t (Пример выше, но в чем-то оптимизирован)
...
Рейтинг: 0 / 0
Переключение между Tab'ами лагает
    #38712926
Фотография _Novichok
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
@k@DElpherА, об это уже много костылей сломано). Но это дело вкуса.
При чем: @k@DElpherView ничего не знает о ViewModel в разных источниках по разному. Но тут с формулировкой вы правее). С другой стороны, как не крути, по факту, и представление и модель представления пишутся совместно. По научному раздельно, по факту вы за ранее знаете что вам во ViewModel нужен будет SelectedItem, если используется ListBox и IsSelected для каждого элемента, если используется дерево. Кто-то даже умудряется во ViewModel запихать свойства Visibility, потому что не хочется писать биндинги с конвертерами, а ведь можно так и так сделать. И в каждом случае нужно знать на что способен XAML и, что действительно потребуется от ViewModel.

С меня оффтоп).

В общем, не все там в WPF под MVVM заточено хорошо.
Согласен, в каждом конкретном случае надо вертеть, как получается.
Я просто часто пытаюсь делать универсальнее и с меньшими затратами
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
Переключение между Tab'ами лагает
    #39201370
kariaja
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
_Novichok, аналогичная проблема. Могу просить совета, как вы решили вопрос потери узлов treeview?
...
Рейтинг: 0 / 0
Переключение между Tab'ами лагает
    #39201377
Roman Mejtes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kariaja_Novichok, аналогичная проблема. Могу просить совета, как вы решили вопрос потери узлов treeview?
нужно просто вынести свойство IsSelected и IsExpanded в модель представления, забиндить через стиль для TreeViewItem эти свойства. За остальное отвечает CollectionView (прокрутка, текущий элемент и т.д.
когда вы открываете там, создается новое визуальное дерево, но коллекция к которой биндится TreeView (ItemSource) находится в ViewModel, для этой коллекции существует CollectionView.
когда вы переключаете вкладку, так как IsExpanded свойство не вынесено из View в ViewModel оно создается по умолчанию со значением False.
...
Рейтинг: 0 / 0
13 сообщений из 13, страница 1 из 1
Форумы / WPF, Silverlight [игнор отключен] [закрыт для гостей] / Переключение между Tab'ами лагает
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]