wpf - vertical - TabItem en un XAML separado
wpf tabcontrol vertical (4)
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 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 con nombre para cada TabItem en un archivo de recursos por separado, por ejemplo, cree un MyResources.xaml que tenga este aspecto:
<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 fusiona en el diccionario de recursos:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="MyResources.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
Finalmente, en su aplicación usted aprovecharía estos Estilos simplemente haciendo:
<TabItem Style="{DynamicResource MyTabItem}" />
¿Es posible poner un TabItem en un XAML separado y hacer referencia a algo como esto?
<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, no funciona, pero me pregunto cómo puedo hacer esto.
Si lo que quiere 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.
Supongamos que su código original fue este:
<TabControl>
<TabItem Header="Tab 1">
<Grid>
<TextBlock Text="Tab Data" />
</Grid>
</TabItem>
</TabControl>
Para que el código sea más manejable, puede dividir el contenido de la pestaña en un UserControl como, por ejemplo:
<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 usa ese control de usuario en tu TabControl así:
<TabControl>
<TabItem Header="Tab 1">
<tabData:Tab1Data />
</TabItem>
</TabControl>
Si realmente desea incluir TabItem en su control de usuario, 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 el código detrás).
Esto te dejará con un control de pestaña que se ve así:
<TabControl>
<tabData:TabItem1 />
<tabData:TabItem2 />
<tabData:TabItem3 />
</TabControl>
Y cada TabItem1 ''User Control'' sería de tipo TabItem. Aquí hay 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 mencioné, asegúrese de cambiar el código para que amplíe TabItem en lugar de usar el control del usuario:
public partial class TabItem1 : TabItem
{
public TabItem1()
{
InitializeComponent();
}
}
Creo que lo que quería era conseguir que TabItem Content declarara 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 Separado:
<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 puedes tener contenido 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>
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 que el código sea más fácil de administrar, se recomienda 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. 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.
Supongamos 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, los contenidos de las pestañas se pueden mover a un UserControl 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 luego es posible utilizar el nuevo control de usuario en el TabControl de esta manera:
<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 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.