2010-06-09 29 views
6

Estoy tratando de crear una aplicación que tendrá pestañas donde cada pestaña tendrá un área de botones y una vista.Cómo reutilizar diseños en WPF

Ahora cada pestaña tendrá esencialmente el mismo diseño simplemente diferentes cosas en el diseño y quería poder reutilizar el mismo diseño para que no tenga que cambiar en muchos lugares (simplemente no es una buena programación). ¿Puedo lograr esto usando recursos o tal vez estilos?

Proporcione un ejemplo de código de luz si es posible.

EDIT: he decidido agregar un ejemplo de lo que estoy tratando de hacer porque todavía no lo entiendo.

Bajo cada TabItem que estoy tratando de recrear esta rejilla (Es un poco más complicado, pero se entiende la idea):

<Grid> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="200"/> 
      <RowDefinition Height="*" /> 
     </Grid.RowDefinitions> 

     <Border Margin="10" 
          BorderBrush="{StaticResource MediumColorBrush}" 
          CornerRadius="10" 
          BorderThickness="2" 
          Grid.Row="0"> 

       <!-- First content goes here --> 

     </Border> 

     <Border Margin="10" 
          BorderBrush="{StaticResource MediumColorBrush}" 
          CornerRadius="10" 
          BorderThickness="2" 
          Grid.Row="1"> 

       <!-- Second content goes here --> 

     </Border> 

    </Grid> 

como se puede ver también las fronteras 2 son los mismos. Ahora necesito poner algún marcador de posición de contenido donde están mis comentarios. Quiero declarar este diseño de Grilla en un diccionario de recursos y luego, donde lo uso, pongo contenido separado en cada borde.

Puede tener muchos TabItems, por lo que repetir este código no es una buena idea y cada página de pestaña tendrá contenido diferente en los 2 marcadores de posición.

soy capaz de usar la cosa

<ContentPresenter Content="{Binding}" /> 

pero sólo por 1 contenido, lo que sucede cuando habrá más.

Respuesta

1

Ingo,

El código está siempre disponible en MSDN. Verifique esto: UserControl, Custom controls, DataTemplates.

Aquí hay algunos ejemplos de cada enfoque. En aras de la simplicidad, supongamos que el diseño que desea replicar es una línea de texto con un primer plano verde (en realidad puede ser realmente diferente, pero se entiende la idea).


1. Control de Usuario

Xaml:

<UserControl x:Class="WpfApplication1.GreenTextUserControl" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 
    <TextBlock x:Name="txt" Foreground="Green"/> 
</UserControl> 

C#:

using System.Windows.Controls; 

namespace WpfApplication1 
{ 
    public partial class GreenTextUserControl : UserControl 
    { 
    public string Text 
    { 
     get { return txt.Text;} 
     set { txt.Text = value; } 
    } 

    public GreenTextUserControl() 
    { 
     InitializeComponent(); 
    } 
    } 
} 

control de ficha:

<TabControl> 
    <TabItem Header="Tab 1"> 
    <loc:GreenTextUserControl Text="This is Tab 1"/> 
    </TabItem> 
    <TabItem Header="Tab 2"> 
    <loc:GreenTextUserControl Text="This is Tab 2"/> 
    </TabItem> 
    <TabItem Header="Tab 3"> 
    <loc:GreenTextUserControl Text="This is Tab 3"/> 
    </TabItem> 
</TabControl> 

2.control personalizado

C#:

public class GreenTextBlock : TextBlock 
    { 
    public GreenTextBlock() 
    { 
     Foreground = Brushes.Green; 
    } 
    } 

TabControl:

<TabControl> 
    <TabItem Header="Tab 1"> 
    <loc:GreenTextBlock Text="This is Tab 1"/> 
    </TabItem> 
    <TabItem Header="Tab 2"> 
    <loc:GreenTextBlock Text="This is Tab 2"/> 
    </TabItem> 
    <TabItem Header="Tab 3"> 
    <loc:GreenTextBlock Text="This is Tab 3"/> 
    </TabItem> 
</TabControl> 

Si su diseño es más complejo que el bloque de texto, controles personalizados también le permite definir en XAML pero difiere de UserControls.


3. DataTemplate

<Window x:Class="WpfApplication1.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:System="clr-namespace:System;assembly=mscorlib" 
     Title="MainWindow" Height="350" Width="525"> 
    <Window.Resources> 
    <x:Array x:Key="GreenText" Type="{x:Type System:String}"> 
     <System:String>This is Tab 1</System:String> 
     <System:String>This is Tab 2</System:String> 
     <System:String>This is Tab 3</System:String> 
    </x:Array> 

    <!--Tab item content data template--> 
    <DataTemplate x:Key="GreenTextTemplate"> 
     <TextBlock Text="{Binding}" Foreground="Green"/> 
    </DataTemplate> 
    </Window.Resources> 
    <Grid> 
    <TabControl ItemsSource="{StaticResource GreenText}"> 
     <TabControl.ItemContainerStyle> 
     <Style TargetType="{x:Type TabItem}"> 
      <Setter Property="ContentTemplate" Value="{StaticResource GreenTextTemplate}"/> 
     </Style> 
     </TabControl.ItemContainerStyle> 
    </TabControl> 
    </Grid> 
</Window> 

Eso es todo :). Espero eso ayude.

+0

Gracias, todavía me estoy volviendo loco con WPF. Ahora me acabo de dar cuenta de la posibilidad de crear mi propia clase que hereda de TabItem pero tiene la estructura lista. Aunque no estoy seguro de si esto funciona, ya que no sé cómo agregar cosas en los diseños. –

+0

Ok, descubrí que no puedes heredar clases Xaml, así que eso no me sirve. Todos los artículos que mencionaste tratan sobre la personalización de controles que no reutilizan los diseños y si quisieras decir que podría personalizar el TabItem o algo para que esto funcione, no lo estoy viendo. –

+0

Personalizar TabItem no me parece correcto (aunque puede hacerlo a través de controles personalizados). En su lugar, podría crear un control de usuario y colocarlo dentro de cada TabItem. Una solución más elegante es crear DataTemplate y usarlo como ItemTemplate para el TabControl ... – Anvaka

3

TabItem es un ContentControl que permite cualquier contenido secundario, pero también permite la creación de plantillas del contenido, que es exactamente lo que estás tratando de hacer. Puede usar un DataTemplate como este para hacer su diseño compartido. ContentPresenter es el marcador de posición para el contenido diferente de cada TabItem.

<DataTemplate x:Key="ButtonViewerTemplate"> 
    <DockPanel> 
     <Button DockPanel.Dock="Bottom" Content="OK"/> 
     <Button DockPanel.Dock="Bottom" Content="Cancel"/> 
     <Border Background="Aqua" BorderBrush="Red" BorderThickness="2" Padding="5"> 
      <ContentPresenter Content="{Binding}" /> 
     </Border> 
    </DockPanel> 
</DataTemplate> 

Para utilizar la plantilla simplemente configúrela en ContentTemplate de cada TabItem. Esto funciona con cualquier cosa derivada de ContentControl.

<TabControl> 
    <TabItem ContentTemplate="{StaticResource ButtonViewerTemplate}" Header="Some Buttons"> 
     <UniformGrid> 
      <Button Content="XXXXX"/> 
      <Button Content="XXXXX"/> 
      <Button Content="XXXXX"/> 
      <Button Content="XXXXX"/> 
     </UniformGrid> 
    </TabItem> 
    <TabItem ContentTemplate="{StaticResource ButtonViewerTemplate}" Header="All Blue"> 
     <Border Background="Blue" MinHeight="50"/> 
    </TabItem> 
    <TabItem ContentTemplate="{StaticResource ButtonViewerTemplate}" Header="Image"> 
     <Image Source="http://i.msdn.microsoft.com/Platform/Controls/StoMastheadMSDN/resources/logo_msdn.png"/> 
    </TabItem> 
</TabControl> 
+0

OK digamos que tengo una grilla dentro del TabItem. Definiría la grilla dentro de DataTemplate. Pero, ¿qué ocurre si luego quiero agregar contenido a la cuadrícula de manera diferente entre las pestañas? Quizás debería definir un estilo de cuadrícula y usarlo en cada cuadrícula, pero no estoy seguro de cómo definir los tamaños de filas y columnas en un estilo de cuadrícula. –

+0

Tanto DataTemplate como el Contenido de TabItem pueden contener cualquier cosa, incluidos Paneles como Grid. Cualquier cosa que necesite ser diferente entre los elementos con plantilla solo puede colocarse en el Contenido de TabItem. –

+0

Bien, ¿quiere decir que la UniformGrid que crea en la segunda ventana de código se colocará en el borde de color Aqua en la primera ventana reemplazando al tipo de contenido/vinculante? –