2010-05-21 23 views
19

Tengo una ventana con control de pestañas y número de páginas: elementos de pestañas. Cada elemento de pestaña tiene el mismo diseño de cuadrícula: 6 filas y 4 columnas. Ahora, cada elemento de pestaña contiene una cuadrícula con definiciones de fila y columna, por lo que casi la mitad de XAML es definición de cuadrículas.Cómo crear un diseño de cuadrícula WPF reutilizable

¿Cómo puedo definir esta cuadrícula en un solo lugar y volver a utilizar esa definición en mi aplicación? ¿Modelo? ¿Control de usuario?

Además de 6x4, tengo solo dos dimensiones más que se repiten: 8x4 y 6x6.

Editar:
olvidó mencionar: controles en cuadrícula son diferentes para cada ficha. Solo quiero que la cuadrícula se defina una vez en algún recurso para que pueda reutilizarlos en diferentes páginas de pestañas. Ahora XAML se ve así:

definición
<TabControl> 
     <TabItem Header="Property"> 
      <Grid> 
       <Grid.RowDefinitions> 
        <RowDefinition /> 
        <RowDefinition /> 
        <RowDefinition /> 
        <RowDefinition /> 
        <RowDefinition /> 
        <RowDefinition /> 
       </Grid.RowDefinitions> 
       <Grid.ColumnDefinitions> 
        <ColumnDefinition /> 
        <ColumnDefinition /> 
        <ColumnDefinition /> 
        <ColumnDefinition /> 
       </Grid.ColumnDefinitions> 
       <!-- some controls here --> 
      </Grid> 
     </TabItem> 
     <TabItem Header="Style"> 
      <Grid > 
       <Grid.RowDefinitions> 
        <RowDefinition /> 
        <RowDefinition />       
        <RowDefinition /> 
        <RowDefinition /> 
        <RowDefinition /> 
        <RowDefinition /> 
       </Grid.RowDefinitions> 
       <Grid.ColumnDefinitions> 
        <ColumnDefinition /> 
        <ColumnDefinition />       
        <ColumnDefinition /> 
        <ColumnDefinition /> 
       </Grid.ColumnDefinitions> 
       <!-- some controls here --> 
      </Grid> 
     </TabItem> 

     ... and this repeats for several more tab items 

    </TabControl> 

Esta rejilla se repite para cada elemento de ficha en el formulario. Me molesta que la mitad de XAML sea una definición de grilla.

¿Hay alguna manera de definir esta cuadrícula en un lugar y luego reutilizar esa definición?

Respuesta

0

Normalmente, uno escribiría una plantilla de datos para los datos que van a las pestañas. Esa plantilla de datos contendría la cuadrícula.

0

¿Cómo puedo definir esta cuadrícula en un solo lugar y volver a utilizar esa definición en mi aplicación? ¿Modelo? ¿Control de usuario?

Si yo fuera usted, me gustaría crear un UserControl o una costumbre Control con el código repetido, y luego simplemente consumen que el control del código actual.

Otro enfoque sería usar un DataTemplate o un ControlTemplate.

La creación de un ControlTemplate para el TabItem s también funcionaría de maravilla.

25

La mejor manera en mi opinión sería utilizar ItemsControl con un ItemsPanelTemplate, ya que se necesita un recipiente por varios elementos:

<FrameworkElement.Resources> 
    <Style x:Key="GridItemsStyle" 
      TargetType="ItemsControl"> 
     <Setter Property="ItemsPanel"> 
      <Setter.Value> 
       <ItemsPanelTemplate> 
        <Grid> 
         <Grid.RowDefinitions> 
          <RowDefinition /> 
          <RowDefinition /> 
          <RowDefinition /> 
          <RowDefinition /> 
          <RowDefinition /> 
          <RowDefinition /> 
         </Grid.RowDefinitions> 
         <Grid.ColumnDefinitions> 
          <ColumnDefinition /> 
          <ColumnDefinition /> 
          <ColumnDefinition /> 
          <ColumnDefinition /> 
         </Grid.ColumnDefinitions> 
        </Grid> 
       </ItemsPanelTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 
</FrameworkElement.Resources> 
<TabControl> 
    <TabItem> 
     <ItemsControl Style="{StaticResource GridItemsStyle}"> 
      <TextBlock Grid.Row="1" Text="R1" /> 
      <TextBlock Grid.Column="1" 
         Text="C1" /> 
     </ItemsControl> 
    </TabItem> 
    <TabItem> 
     <ItemsControl Style="{StaticResource GridItemsStyle}"> 
      <TextBlock Grid.Row="2" 
         Text="R2" /> 
      <TextBlock Grid.Column="2" 
         Text="C2" /> 
     </ItemsControl> 
    </TabItem> 
</TabControl> 
+0

Funciona tan simple como se ve –

+0

¡Excelente respuesta! Esto era justo lo que estaba buscando, muchas gracias por compartir :-) –

1

tuve algo similar. La pregunta es ¿cómo quieres poner tus datos en las cuadrículas?

Como usa el mismo diseño una y otra vez, creo que está poniendo cosas similares en cada celda.

Creé un ItemsControl personalizado para cada pestaña para colocar los datos y luego creé un estilo para ItemsControl que mostraba la cuadrícula.

<Style x:Key="GridItemsStyle" 
     TargetType="ItemsControl"> 
    <Setter Property="ItemsPanel"> 
     <Setter.Value> 
      <ControlTemplate> 
       <Grid> 
        <Grid.RowDefinitions> 
         <RowDefinition /> 
         <RowDefinition /> 
         <RowDefinition /> 
         <RowDefinition /> 
         <RowDefinition /> 
         <RowDefinition /> 
        </Grid.RowDefinitions> 
        <Grid.ColumnDefinitions> 
         <ColumnDefinition /> 
         <ColumnDefinition /> 
         <ColumnDefinition /> 
         <ColumnDefinition /> 
        </Grid.ColumnDefinitions> 

        <ContentPresenter Content="{Binding ElementName=Cell00}" Grid.Row="0" Grid.Column="0" /> 

        <ContentPresenter Content="{Binding ElementName=Cell01}" Grid.Row="0" Grid.Column="1" /> 

        <ContentPresenter Content="{Binding ElementName=Cell10}" Grid.Row="1" Grid.Column="0" /> 


        <!-- ...And so on --> 

       </Grid> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

y en la ventana

<TabControl> 
<TabItem> 
    <local:tab1 Style="{StaticResource GridItemsStyle}" /> 
</TabItem> 
<TabItem> 
    <local:tab2 Style="{StaticResource GridItemsStyle}" /> 
</TabItem> 

entonces cada CustomControl hereda de ItemsControl

<ItemsControl x:Class="your_app.tab1" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:local="clr-namespace:your_app"> 

<ContentControl x:Name="Cell00"> 

    <!-- Some stuff here --> 

</ContentControl> 
<ContentControl x:Name="Cell01"> 

    <!-- Some stuff here --> 

</ContentControl> 
<ContentControl x:Name="Cell10"> 

    <!-- Some stuff here --> 

</ContentControl> 

Esto es muy similar a lo que Aelij está haciendo, excepto fijo el ContentPresenter y vincularlo a un nombre y poner los elementos de control en su propia cosa (puede mezclar b otras soluciones).

Todavía es una gran cantidad de código, pero yo diría que se guarda todas las definiciones de filas y columnas todo el tiempo y también solo tiene que cambiar la cuadrícula en un lugar si tiene que modificarlo un poco.

3

O simplemente puede heredar de la rejilla ...

using System.Windows.Controls; 
public class AlreadySetupGrid:Grid 
{ 
    public AlreadySetupGrid() 
    { 
     for (int i = 0; i < 4; i++) 
     { 
      ColumnDefinitions.Add(new ColumnDefinition()); 
     } 
     for (int i = 0; i < 6; i++) 
     { 
      RowDefinitions.Add(new RowDefinition()); 
     } 
    } 
} 

y luego usar que en lugar de su cuadrícula normal.

+0

esto sonaba como un mejor plan, pero esto no era así, ya que no obtengo las columnas y las filas en el tiempo del diseño. es decir, cualquier elemento definido en la cuadrícula no se colocará correctamente – Gurpreet

0

Puede hacerlo, pero requiere algo de trabajo:

1) Crear una colección y una propiedad adjunta como esto:

public class ColumnDefinitions : Collection<ColumnDefinition> 
{ 
    public static readonly DependencyProperty SourceProperty = DependencyProperty.RegisterAttached(
     "Source", 
     typeof(ColumnDefinitions), 
     typeof(ColumnDefinitions), 
     new PropertyMetadata(
      default(ColumnDefinitions), 
      OnColumnDefinitionsChanged)); 

    public static void SetSource(Grid element, ColumnDefinitions value) 
    { 
     element.SetValue(SourceProperty, value); 
    } 

    [AttachedPropertyBrowsableForChildren(IncludeDescendants = false)] 
    [AttachedPropertyBrowsableForType(typeof(Grid))] 
    public static ColumnDefinitions GetSource(Grid element) 
    { 
     return (ColumnDefinitions)element.GetValue(SourceProperty); 
    } 

    private static void OnColumnDefinitionsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     var grid = (Grid)d; 
     grid.ColumnDefinitions.Clear(); 
     var columnDefinitions = (ColumnDefinitions)e.NewValue; 
     if (columnDefinitions == null) 
     { 
      return; 
     } 

     foreach (var columnDefinition in columnDefinitions) 
     { 
      grid.ColumnDefinitions.Add(columnDefinition); 
     } 
    } 
} 

2) A continuación, se puede usar como un recurso y en una estilo para la red como esta: Tenga en cuenta que x:Shared="False" se debe utilizar. Si no, se agregará la misma definición a muchas cuadrículas que provocan que WPF lance.

<UserControl.Resources> 
    <demo:ColumnDefinitions x:Key="SomeColumnDefinitions" x:Shared="False"> 
     <ColumnDefinition Width="Auto" /> 
     <ColumnDefinition Width="*" /> 
    </demo:ColumnDefinitions> 

    <Style x:Key="SomeGridStyle" TargetType="{x:Type Grid}"> 
     <Setter Property="demo:ColumnDefinitions.Source" Value="{StaticResource SomeColumnDefinitions}"></Setter> 
    </Style> 
</UserControl.Resources> 
<Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition /> 
     <RowDefinition Height="5"/> 
     <RowDefinition /> 
    </Grid.RowDefinitions> 
    <Grid Style="{StaticResource SomeGridStyle}"> 
     <Rectangle Grid.Row="0" 
        Grid.Column="0" 
        Width="120" 
        Fill="Blue" /> 
     <Rectangle Grid.Row="0" 
        Grid.Column="1" 
        Fill="Yellow" /> 
    </Grid> 

    <Grid Grid.Row="2" demo:ColumnDefinitions.Source="{StaticResource SomeColumnDefinitions}"> 
     <Rectangle Grid.Row="0" 
        Grid.Column="0" 
        Width="120" 
        Fill="Blue" /> 
     <Rectangle Grid.Row="0" 
        Grid.Column="1" 
        Fill="Yellow" /> 
    </Grid> 
</Grid> 
Cuestiones relacionadas