2009-10-19 22 views
16

¿Es posible poner un TabItem en una XAML y referencia separada o menos así:TabItem en un XAML separada

<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> 

Por supuesto que no funciona, pero me pregunto cómo puedo hacer esto?

Respuesta

31

Si lo que desea hacer es simplemente hacer que el código sea más manejable, le recomendaría definir los datos de cada pestaña en un control de usuario, pero aún así tener el TabItem en el control de la pestaña principal.

Vamos a suponer que el código original era la siguiente:

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

Para que el código sea más manejable que podría romper el contenido de la ficha en un control de usuario, tales como:

<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> 

y luego usar ese usuario control en su TabControl como este:

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

Si realmente desea incluir th e TabItem en su control de usuario, entonces puede hacerlo creando primero un control de usuario, y luego cambie el tipo de control de usuario al tipo TabItem (asegúrese de cambiar esto tanto en el nodo raíz xaml como en el código subyacente).

Esto le deja con un control de ficha que se ve así:

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

Y cada TabItem1 'Control de Usuario' sería de tipo TabItem. Aquí está un ejemplo:

<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> 

Y como he mencionado, es importante cambiar el código subyacente para que se extienda TabItem en lugar de control de usuario:

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

Muchas gracias. ¡Funciona perfectamente como lo demostró en su respuesta! –

+12

tabdata viene de donde? –

+0

¿Cómo hiciste para que funcione la propiedad 'xmlns' como lo has mostrado? Por lo que yo sé, requiere estar en una asamblea extranjera. –

2

En la superficie esto parece que sería mejor resolverlo con un estilo y/o plantilla para el control TabItem que puede almacenar en un archivo de recursos por separado. La cantidad que necesite para personalizar el TabItem real determinará si puede usar un estilo o si necesita una plantilla.

Lo que puede hacer es definir un estilo para cada llamada TabItem en un archivo de recursos independiente como tal, crear un MyResources.xaml que se ve algo como esto:

<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> 

Luego, en su archivo principal App.xaml se fusionan en el diccionario de recursos:

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

último en su aplicación que permitiría la obtención de estos estilos simplemente haciendo:

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

Lo siento, debería haber elaborado más. No voy después de la reutilización, pero haciendo que mi código sea más manejable. Ahora mismo tengo todo mi XAML en mi ventana principal. Los artículos más voluminosos están contenidos en un TabControl. Desbloquear los TabItems que contienen varios controles, haría que fuera mucho más fácil tratar con ellos. Solo soy un principiante, así que no estoy seguro de cuál es el mejor enfoque. Examinaré la creación de una plantilla para TabItem. –

+1

Ok, aún creo que el enfoque de estilo/plantilla que he sugerido es una buena solución para esto. Elaboraré en mi respuesta. –

+0

-1 John Sheares estaba pidiendo una forma de dividir archivos XAML, no reducir el código redundante. –

1

Creo que lo que quería es conseguir TabItem Contenido declarar por separado Como TabItem es un ContentControl, puede presentar un UserControl como su contenido.

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

En XAML independiente:

<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> 

En otro XAML que puede tener un contenido de 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> 
+0

Esto también funciona. Una cosa que noté es que tengo que redefinir mis recursos nuevamente dentro del contenido de la pestaña XAML porque los que están definidos para la ventana no están disponibles. Además, ¿cómo obtengo un control que está en una de las pestañas del código subyacente de la ventana que contiene el TabControl? ¿Uso FindName()? –

11

La respuesta anterior de Tony Borres ya cubre los aspectos más importantes. Pero el comentario adicional solicita acceso desde el código subyacente. Así que extenderé el ejemplo de Tony para mostrar este aspecto también. Esta respuesta muestra los espacios de nombres requeridos. Los he agregado a la respuesta de Tony, también.

Para simplemente hacer que el código sea más manejable, se recomienda definir los datos de cada pestaña en un control de usuario, pero aún tener el TabItem en el control de la pestaña principal. Esta estrategia es útil, por ejemplo, para evitar el uso de FxCop CA1505: "Evitar código no memorizable" cuando se usa un control de tabulación con varios elementos de tabulación.

Vamos a suponer que este es el código original:

<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> 

Para que el código sea más manejable el contenido de la pestaña se pueden mover en un control de usuario, tales como:

<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> 

Y entonces es posible utilice el nuevo control de usuario en el TabControl como este:

<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> 

Ahora es posible para acceder a las wigs internas del control de usuario desde la ventana principal y viceversa. Tenga en cuenta la "x:" delante del nombre del control del usuario.

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"; 
    } 
} 

El código que se muestra para acceder a txtData2 sería el mismo aunque esté incrustado en su propio control de usuario.

Cuestiones relacionadas