Подтвердить что ты не робот

TabItem в отдельном XAML

Можно ли поместить TabItem в отдельный XAML и ссылаться на что-то вроде этого:

<TabControl>
     <local:MyTabItem/>
</TabControl>



In Separate XAML:
<UserControl x:Class="MyProject.MyTabItem"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <TabItem Header="MyTab">

    </TabItem>
</UserControl>

Конечно, это не сработает, но мне интересно, как я могу это сделать?

4b9b3361

Ответ 1

Если то, что вы хотите сделать, просто сделать код более управляемым, я бы рекомендовал определять данные каждой вкладки в пользовательском элементе управления, но все же иметь TabItem в главном элементе управления вкладкой.

Предположим, что ваш исходный код был следующим:

<TabControl>
    <TabItem Header="Tab 1">
        <Grid>
            <TextBlock Text="Tab Data" />
        </Grid>
    </TabItem>
</TabControl>

Чтобы сделать код более управляемым, вы можете разбить содержимое вкладки в UserControl, например:

<UserControl x:Class="WpfApplication19.Tab1Data"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             >
    <Grid>
        <TextBlock Text="Tab Data" />
    </Grid>
</UserControl>

И затем используйте этот элемент управления пользователя в свой TabControl следующим образом:

    <TabControl>
        <TabItem Header="Tab 1">
            <tabData:Tab1Data />
        </TabItem>
    </TabControl>

Если вы действительно хотите включить TabItem в свой пользовательский элемент управления, тогда вы можете сделать это, сначала создав пользовательский элемент управления, а затем измените тип пользовательского элемента управления на тип TabItem (убедитесь, что вы изменили его как в xaml root node и код позади).

Это оставит вас с помощью элемента управления табуляции, который выглядит так:

    <TabControl>
        <tabData:TabItem1 />
        <tabData:TabItem2 />
        <tabData:TabItem3 />
    </TabControl>

И каждый TabItem1 'User Control' будет иметь тип TabItem. Вот пример:

<TabItem x:Class="WpfApplication19.TabItem1"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         Header="Tab 1"
         >
    <Grid>
        <TextBlock Text="Tab Data" />
    </Grid>
</TabItem>

И, как я уже упоминал, обязательно измените код, чтобы он расширил TabItem вместо пользовательского элемента управления:

public partial class TabItem1 : TabItem
{
    public TabItem1()
    {
        InitializeComponent();
    }
}

Ответ 2

Предыдущий ответ Тони Борреса уже охватывает наиболее важные аспекты. Но дальнейший комментарий требует доступа из кода позади. Поэтому я продолжу пример от Тони, чтобы показать этот аспект. Этот ответ показывает требуемые пространства имен. Я также добавил их к ответу от Тони.

Чтобы просто сделать код более управляемым, рекомендуется определять каждую вкладку данных в пользовательском элементе управления, но все же иметь TabItem в элементе управления главной вкладкой. Эта стратегия полезна, например, для работы с FxCop CA1505: "Избегайте недостижимого кода" при использовании элемента управления вкладкой с несколькими элементами табуляции.

Предположим, что это исходный код:

<Window x:Class="WpfApplication19.MainWindow" ...>
    <TabControl>
        <TabItem Header="Tab 1">
            <Grid>
                <TextBlock Text="Data on Tab 1" Name="txtData1" />
            </Grid>
        </TabItem>
        <TabItem Header="Tab 2">
            <Grid>
                <TextBlock Text="Data on Tab 2" Name="txtData2" />
            </Grid>
        </TabItem>
    </TabControl>
</Window>

Чтобы сделать код более управляемым, содержимое вкладки можно перенести в UserControl, например:

<UserControl x:Class="WpfApplication19.Tab1Data"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             Loaded="OnControlLoaded"
             >
    <Grid>
        <TextBlock Text="Data on Tab 1" Name="txtData1" />
    </Grid>
</UserControl>

И тогда можно использовать новый элемент управления пользователя в TabControl следующим образом:

<Window x:Class="WpfApplication19.MainWindow"
        xmlns:tabData="clr-namespace:WpfApplication19" ...>
    <TabControl>
        <TabItem Header="Tab 1">
            <tabData:Tab1Data x:Name="ucTab1Data" />
        </TabItem>
        <TabItem Header="Tab 2">
            <Grid>
                <TextBlock Text="Data on Tab 2" Name="txtData2"/>
            </Grid>
        </TabItem>
    </TabControl>
</Window>

Теперь можно получить доступ к внутренним виджетам пользовательского элемента управления из главного окна и наоборот. Обратите внимание на "x:" перед именем пользователя.

public partial class MainWindow : Window
{
    private void AccessWidgetWithinUserControl()
    {
        ucTab1Data.txtData1.Text = "New text on Tab 1";
    }
}

public partial class Tab1Data : UserControl
{
    private MainWindow mainWindow = null; // Reference to the MainWindow

    public Tab1Data()
    {
        InitializeComponent();
    }

    // get a reference to main windows when it is available.
    // The Loaded Event is set in the XAML code above.
    private void OnControlLoaded(object sender, RoutedEventArgs e)
    {
        mainWindow = Window.GetWindow(this) as MainWindow;
    }

    private void AccessMainWindowsWidget()
    {
        mainWindow.txtData2.Text = "New text on Tab 2 in the main window";
    }
}

Показанный код для доступа к txtData2 будет таким же, даже если он встроен в свой собственный пользовательский элемент управления.

Ответ 3

На первый взгляд кажется, что лучше всего решить стиль и/или шаблон для элемента управления TabItem, который можно сохранить в отдельном файле ресурсов. Сколько вам нужно для настройки фактического TabItem будет определять, можете ли вы просто использовать стиль или если вам нужен шаблон.

Что вы можете сделать, так это определить именованный стиль для каждого TabItem в отдельном файле ресурсов, например, создать файл MyResources.xaml, который выглядит примерно так:

<ResourceDictionary>
    <Style x:Key="MyTabItem" TargetType="{x:Type TabItem}">
      <!-- 
           you can just use simple property setters to set up 
           the TabItem or set the Template property to replace
           entire tab look and feel
      -->
    </Style>
</ResourceDictionary>

Затем в вашем основном файле App.xaml вы объединяетесь в словарь ресурсов:

<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="MyResources.xaml"/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Application.Resources>

Наконец, в вашем приложении вы будете использовать эти стили, просто сделав:

<TabItem Style="{DynamicResource MyTabItem}" />

Ответ 4

Я думаю, что вы хотите, чтобы получить содержимое TabItem Content отдельно. Поскольку TabItem является ContentControl, вы можете представить UserControl в качестве его содержимого.

<TabControl>
   <TabItem> 
       <local:YourTabContent1/>
   </TabItem>
   <TabItem> 
       <local:YourTabContent2/>
   </TabItem>
</TabControl>

В отдельном XAML:

<UserControl x:Class="MyProject.YourTabContent1"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <......blah blah.../>
</UserControl>

В другом XAML вы можете иметь контент 2

<UserControl x:Class="MyProject.YourTabContent2"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
   <......blah blah.../>
</UserControl>