powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / WPF, Silverlight [игнор отключен] [закрыт для гостей] / TabControl как в VS
5 сообщений из 5, страница 1 из 1
TabControl как в VS
    #39065894
Фотография Referee
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Добрый день.

Пытаюсь сделать TabControl как в VS с возможностью выбора вкладок из выпадающего меню.
Так же хотелось бы иметь разные TabItem (без возможности закрытия, с возможностью закрытия, и с возможностью закрытия + пометкой если что-то поменялось)

чтобы менять TabItem - делаю шаблон (пока просто с текстом, потом туда же добавлю кнопку закрытия и пометку об изменении)

Код: xml
1.
2.
3.
                    <DataTemplate x:Key="TabItemItemTemplate" DataType="{x:Type TabItem}">
                        <TextBlock Text="{Binding Caption}"/>
                    </DataTemplate>



для меню и общего вида делаю стиль.

Код: 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.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:sys="clr-namespace:System;assembly=mscorlib"
                    >
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="CommonSimpleBlueStyle.xaml"/>
    </ResourceDictionary.MergedDictionaries>


    <SolidColorBrush x:Key="Background" Color="#FFCBEAFF" />
    <SolidColorBrush x:Key="BackgroundSelected" Color="White" />
    <SolidColorBrush x:Key="BorderBrush" Color="#FF808080" />
    <SolidColorBrush x:Key="BorderBrushSelected" Color="White" />


    <!--Ключевые размеры элементов-->
    <sys:Double x:Key="ButtonWidthAndHeight">16</sys:Double>

    <!--Выпадающее меню с перечнем TabItems-->
    <Geometry x:Key="TabMenuButton">M0,1 H0,5 M7,8 L0,8 0,2 10,2 L10,5 M10,8 L10,10 8,10Z</Geometry>
    <Path x:Key="TabMenuButtonPath"
            Margin="2"
            Data="{StaticResource TabMenuButton}"
            Stroke="{StaticResource BorderBrush}" 
            Fill="{StaticResource Background}"
            Stretch="Fill"
            VerticalAlignment="Center"
            HorizontalAlignment="Center"/>

    <Style x:Key="TabMenuItem" TargetType="{x:Type MenuItem}">
        <Setter Property="Header" Value="{Binding Path=Header}"/>
        <Setter Property="IsEnabled" Value="{Binding Path=IsEnabled}" />
        <Setter Property="IsCheckable" Value="{Binding Path=IsEnabled}" />
        <Setter Property="IsChecked" Value="{Binding Path=IsSelected, Mode=TwoWay}" />
        <Setter Property="Foreground" Value="{StaticResource BorderBrush}"/>
    </Style>

    <Style x:Key="TabMenuButtonStyle" TargetType="{x:Type MenuItem}">
        <Setter Property="Focusable" Value="False"/>
        <Setter Property="Height" Value="{StaticResource ButtonWidthAndHeight}"/>
        <Setter Property="Width" Value="{StaticResource ButtonWidthAndHeight}"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type MenuItem}">
                    <Border Name="ButtonBorder" Margin="1" 
                          BorderBrush="{StaticResource BorderBrush}" 
                          Background="{StaticResource Background}" 
                          CornerRadius="1" 
                          BorderThickness="1">
                        <Grid>
                            <ContentPresenter 
                                          Content="{StaticResource TabMenuButtonPath}"
                                          HorizontalAlignment="Stretch"
                                          VerticalAlignment="Stretch"/>
                            <Popup Name="Popup"
                               Placement="Bottom"
                               IsOpen="{TemplateBinding IsSubmenuOpen}"
                               AllowsTransparency="True" 
                               Focusable="False"
                               PopupAnimation="Fade">
                                <Border Name="SubmenuBorder"
                                    Margin="1"
                                    SnapsToDevicePixels="True"
                                    BorderBrush="{StaticResource BorderBrush}" 
                                    Background="{StaticResource Background}" 
                                    CornerRadius="1" 
                                    BorderThickness="1">
                                    <StackPanel 
                                        IsItemsHost="True" 
                                        KeyboardNavigation.DirectionalNavigation="Cycle"/>
                                </Border>

                            </Popup>
                        </Grid>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>    
    

    <Style TargetType="{x:Type TabControl}" x:Key="StandardTabControl">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="TabControl">
                    <Grid KeyboardNavigation.TabNavigation="Local">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="*"/>
                        </Grid.RowDefinitions>

                        <Border Name="TabPanelBorder"
                             Height="Auto"
                             Background="{StaticResource Background}"
                                >
                            <Grid>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="*"/>
                                    <ColumnDefinition Width="Auto"/>
                                </Grid.ColumnDefinitions>
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="*"/>
                                    <RowDefinition Height="Auto"/>
                                </Grid.RowDefinitions>
                                <ScrollViewer Grid.Row="0" Grid.RowSpan="2"
                                         VerticalScrollBarVisibility="Disabled"
                                         CanContentScroll="True" 
                                         HorizontalScrollBarVisibility="Hidden"
                                         IsDeferredScrollingEnabled="False"
                                         SnapsToDevicePixels="True"
                                         Name="ScrollViewerTabPanel"
                                         HorizontalAlignment="Stretch"
                                         VerticalAlignment="Stretch"
                                         >
                                    <TabPanel IsItemsHost="True"
                                            x:Name="PART_ScrollContentPresenter"
                                            Margin="4,0,0,0"                                  
                                            KeyboardNavigation.TabIndex="1"/>
                                </ScrollViewer>
                                
                                <StackPanel Grid.Row="1" 
                                       Grid.Column="3"
                                       Orientation="Horizontal"
                                       Margin="5,0,0,4">
                                    <Menu Background="Transparent">
                                        <MenuItem Style="{StaticResource TabMenuButtonStyle}"
                                           ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TabControl}}, Path=Items}"
                                           ItemContainerStyle="{StaticResource TabMenuItem}">
                                        </MenuItem>
                                    </Menu>
                                </StackPanel>
                            </Grid>
                        </Border>

                        <ContentPresenter 
                            Grid.Row="1" 
                            x:Name="PART_SelectedContentHost"
                            ContentSource="SelectedContent" 
                            VerticalAlignment="Stretch"
                            HorizontalAlignment="Stretch"
                            Margin="0"/>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>        
    </Style>

    <Style TargetType="{x:Type TabItem}">
        <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/>
        <Setter Property="TextBlock.FontSize" Value="12"/>
        <Setter Property="TextBlock.Foreground" Value="{StaticResource BorderBrush}"/>

        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type TabItem}">
                    <Grid>
                        <Border Name="TabItemBorder"
                            Background="{StaticResource Background}"
                            BorderBrush="{StaticResource BorderBrush}"
                                                            
                            BorderThickness="2,1,1,0"
                            CornerRadius="3,3,0,0">

                            <ContentPresenter x:Name="ContentHeader" 
                                Margin="7,2,12,2"
                                VerticalAlignment="Center"
                                HorizontalAlignment="Center"
                                ContentSource="Header"
                                RecognizesAccessKey="True"
                            />

                        </Border>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsSelected" Value="True">
                            <Setter Property="Panel.ZIndex" Value="90" />
                            <Setter Property="TextBox.FontWeight" Value="DemiBold"/>
                            <Setter TargetName="TabItemBorder" Property="BorderBrush" Value="{StaticResource BorderBrushSelected}" />
                            <Setter TargetName="TabItemBorder" Property="Margin" Value="0,2,0,0"/>
                        </Trigger>
                        <Trigger Property="IsSelected" Value="False">
                            <Setter Property="Panel.ZIndex" Value="80" />
                            <Setter TargetName="TabItemBorder" Property="Margin" Value="0,4,0,0"/>
                        </Trigger>
                    </ControlTemplate.Triggers>

                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>


</ResourceDictionary>



так вот. если TabControl имеет статические страницы то все работает ок.
если я страницы загружаю извне то меню не заполняется и не переключает вкладки

Код: c#
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.
    class Workspace: DependencyObject
    {
        #region Dependency Properties
        public static readonly DependencyProperty IsSelectedProperty = DependencyProperty.Register("IsSelected", typeof(bool), typeof(Workspace));
        #endregion


        public string Caption { get; set; }

        public Workspace(string caption)
        {
            this.Caption = caption;
        }

        public bool IsSelected
        {
            get
            {
                return (bool)this.GetValue(IsSelectedProperty);
            }
            set
            {
                this.SetValue(IsSelectedProperty, value);
            }
        }


    }

    /// <summary>
    /// Логика взаимодействия для MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private ObservableCollection<Workspace> pages = new ObservableCollection<Workspace>() { new Workspace("test"), new Workspace("test1") };
        
        public MainWindow()
        {
            InitializeComponent();
            DataContext = this.pages;
        }
    }




Код: 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.
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>

        <!--Если заполнять автоматически то меню не работает-->
        <Border Grid.Row="0">
            <TabControl 
                x:Name="DontWorkTabControl"
                ItemsSource="{Binding}" Margin="10"
                IsSynchronizedWithCurrentItem="True" 
                Focusable="False"
                ItemTemplate="{StaticResource ResourceKey=TabItemItemTemplate}"
                >
            </TabControl>
        </Border>

        <Border Grid.Row="1">
            <TabControl 
            x:Name="IsOkTabControl"
            Margin="10"
            IsSynchronizedWithCurrentItem="True" 
            Focusable="False">
                <TabItem Header="test" IsSelected="True">conent</TabItem>
                <TabItem Header="test1">content 1</TabItem>
            </TabControl>
        </Border>

    </Grid>



я так понимаю что проблема при заполнении пунктов меню

Код: xml
1.
2.
3.
4.
    <Style x:Key="TabMenuItem" TargetType="{x:Type MenuItem}">
        <Setter Property="Header" Value="{Binding Path=Header}"/>
        ...
    </Style>



Вопрос как праильно заполнить меню и как его завтасить работать.
в стиле не хочется привязываться к конкретной ViewModel.

Спасибо за ответы!
...
Рейтинг: 0 / 0
TabControl как в VS
    #39066570
Фотография Шайтан
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
авторTabControl как в VS

глянь https://avalondock.codeplex.com/
может поможет. там и в исходниках можно поковыряться
...
Рейтинг: 0 / 0
TabControl как в VS
    #39069257
Фотография Referee
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Шайтан,

Спасибо.
Не совсем то что надо, но как вариант :)

товарищи, может про стили кто-нибудь все таки подскажет?
...
Рейтинг: 0 / 0
TabControl как в VS
    #39069372
Roman Mejtes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В самом VisualStudio это сделано так:
В основе лежит DocumentGroupControl из Microsoft.VisualStudio.Shell.ViewManager.dll
(пространство имен: Microsoft.VisualStudio.PlatformUI.Shell.Controls), который судя по всему наследуется от GroupControl, который скорее всего наследован от ItemsControl или его потомков.
его шаблон состоит из :
Microsoft.VisualStudio.PlatformUI.Shell.Controls.DocumentTabPanel - это панель для заголовков куда ItemsControl (DocumentGroupControl ) запихивает DocumentTabItem'ы, правее этой панели расположена кнопка Microsoft.VisualStudio.PlatformUI.Shell.Controls.DropDownButton - это кнопка с выпадающим меню, в самой кнопке в ресурсах есть CollectionViewSource который судя по всему содержит представление списка вкладок которое извлекается из ItemsSource
И ContentPresenter'а для отображения текущего элемента управления, свойство Content которого меняется через DocumentGroupControl когда пользователь выбирает другую вкладку (там даже связывания нет, как не странно, хотя связывание было бы как по мне удобнее).

Если хочешь делать как в VS можешь начинать делать :)


p.s. контролы кстати public и в сборке они не обфусцированы, по этому можно спокойно посмотреть их код. А устроены они очень и очень просто.
...
Рейтинг: 0 / 0
TabControl как в VS
    #39070087
Фотография Referee
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Roman Mejtes,

Спасибо за ответ!
обязательно копну глубже в эту сторону!
...
Рейтинг: 0 / 0
5 сообщений из 5, страница 1 из 1
Форумы / WPF, Silverlight [игнор отключен] [закрыт для гостей] / TabControl как в VS
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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