2010-06-09 13 views
6

Sto provando a creare un'applicazione che verrà compressa in cui ogni scheda avrà un'area dei pulsanti e un'area di visualizzazione.Come riutilizzare i layout in WPF

Ora ogni scheda avrà essenzialmente lo stesso layout solo diverse cose nel layout e volevo poter riutilizzare lo stesso layout in modo da non dover cambiare in molti punti (non è una buona programmazione). Posso realizzare questo utilizzando risorse o forse stili.

Se possibile, fornire un esempio di codice di illuminazione.

EDIT: Ho deciso di aggiungere un esempio di ciò che sto cercando di fare perché non riesco ancora a ottenerlo.

Sotto ogni TabItem sto cercando di ricreare questa griglia (E 'un po' più complicato, ma si ottiene l'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> 

come si può vedere anche i 2 bordi sono gli stessi. Ora ho bisogno di mettere un segnaposto di contenuto dove sono i miei commenti. Non voglio dichiarare questo layout Grid in un dizionario delle risorse e quindi, dove lo uso, metto un contenuto separato in ciascun bordo.

Posso avere un sacco di TabItems quindi ripetere questo codice non è una buona idea e ogni pagina Tab avrà contenuto diverso nei 2 segnaposti.

sono in grado di utilizzare la cosa

<ContentPresenter Content="{Binding}" /> 

ma solo per 1 il contenuto, ciò che accade quando non ci sarà più.

risposta

1

Ingo,

Codice è sempre disponibile su MSDN. Controllare questo: UserControl, Custom controls, DataTemplates.

Ecco alcuni esempi di ciascun approccio. Per semplicità, supponiamo che il layout che si desidera replicare sia una riga di testo con un primo piano verde (in realtà potrebbe essere molto diverso, ma si ottiene l'idea).


1. controllo utente

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(); 
    } 
    } 
} 

Controllo Tab:

<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.controllo personalizzato

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> 

Se il layout è più complesso di blocco di testo, controlli personalizzati consente inoltre di definire in XAML, ma differisce da 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> 

Questo è tutto :). Spero che sia d'aiuto.

+0

Grazie, ancora avvolgendo la mia testa intorno a WPF. Ora ho appena realizzato la possibilità di creare la mia classe che eredita da TabItem ma ha la struttura pronta. Non sono sicuro se funziona così, perché non so come aggiungere elementi nei layout. –

+0

Ok ho scoperto che non è possibile ereditare le classi Xaml, quindi non è di alcuna utilità per me. Tutti gli articoli che hai menzionato riguardano la personalizzazione dei controlli, non il riutilizzo dei layout e, se vuoi dire che potrei personalizzare il TabItem o qualcosa per farlo funzionare, non lo vedrò. –

+0

Personalizzare TabItem non mi sembra giusto (anche se puoi tramite i controlli personalizzati). Invece è possibile creare un controllo utente e inserirlo in ogni TabItem. La soluzione più elegante è quella di creare DataTemplate e usarlo come ItemTemplate per TabControl ... – Anvaka

3

TabItem è un ContentControl che consente qualsiasi contenuto secondario, ma consente anche la modellazione del contenuto, che è esattamente ciò che si sta tentando di fare. Puoi usare un DataTemplate come questo per fare il tuo layout condiviso. ContentPresenter è il segnaposto per i diversi contenuti di ogni 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> 

Per utilizzare il modello, è sufficiente impostarlo su ContentTemplate di ogni TabItem. Funziona con qualsiasi cosa derivata da 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 diciamo che ho una griglia all'interno del TabItem Definirei la griglia all'interno del DataTemplate. Ma cosa succede se non dovessi aggiungere il contenuto nella griglia in modo diverso tra le schede. Forse dovrei definire uno stile Grid e usarlo su ogni griglia, ma non sono sicuro di come definire le dimensioni di righe e colonne in uno stile di griglia. –

+0

Sia il DataTemplate che il Contenuto TabItem possono contenere qualsiasi cosa, inclusi i pannelli come Grid. Tutto ciò che deve essere diverso tra gli elementi basati su modelli può essere inserito nel Contenuto TabItem. –

+0

Ok, stai dicendo che l'UniformGrid che creerai nel secondo codeWindow verrà inserito nel bordo del colore Aqua nella prima finestra che sostituisce il tipo di contenuto/binding? –

Problemi correlati