2009-11-16 13 views
6

En WPF, quiero crear una ventana que tiene el siguiente aspecto:WPF Disposición de control de usuario como una carrera

Application with user controls http://www.freeimagehosting.net/uploads/86209e1a87.png

En la pantalla son cuatro control de usuario, nº 1, 2, 3, 4. Como puede ver, el control de usuario 2 no se debe representar como un cuadro, sino en línea.

Si esto fuera un documento de flujo de WPF:

  • 1, 3, 4 sería un párrafo (boxeo)
  • 2 a correr (inline)

La razón es que 2 podría usarse en otra forma sin dividir por 3.

¿Tiene alguna idea de cómo hacerlo de manera adecuada?

Algunos idea ya pensado:

  • 2 es un usuario normal y el control (boxeo). Cuando se coloca en la ventana, 2, 3, 4 son colocados en un lienzo, utilizando allí Z-orden y control tonelada margen la forma en que se prestan
  • 2 tiene una rejilla ya formateado para que pudiera aceptar 3 y 4 en ella como ContentControl, y les inyecta a través de Xaml o código detrás
  • 2 expone la red principal como una propiedad, y por medio de la bondad propiedad adjunta, añadimos los datos para 3 y 4
  • creamos nuestro propio control diseño e implemente los métodos Organizar y Medir para crear un diseño que actúe como una Ejecución

Y algunos otros que no son tan limpios ...

¿Alguna idea?

Gracias,

Patrick

Respuesta

1

creo que tenga su forma disuelta de forma incorrecta, la OMI.

El área 2 no debe incluir la pieza inferior que está describiendo que desea tener "en línea".

Debe separar (por lo que la disposición se refiere), y, probablemente, en forma de una rejilla con 2 columnas y 2 filas a lo largo de la Zona 3 y Zona 4. Zona 3 sería entonces necesario tener un rowspan de 2.

El XAML, en este caso, en realidad sería bastante limpio si se hace de esta manera.

Podría ser algo como esto:

<Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition /> 
     <RowDefinition /> 
     <RowDefinition /> 
    </Grid.RowDefinitions> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition /> 
    </Grid.ColumnDefinitions> 

    <uC:Area1 Grid.Row="0"><!-- Area Control here --></uC:Area1> 
    <uC:Area2 Grid.Row="1"><!-- Area Control here --></uC:Area2> 

    <Grid Grid.Row="2"> 
     <Grid.RowDefinitions> 
      <RowDefinition /> 
      <RowDefinition /> 
     </Grid.RowDefinitions> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition /> 
      <ColumnDefinition /> 
     </Grid.ColumnDefinitions> 

     <uC:AreaDuree Grid.Row="0" Grid.Column="0"> 
      <!-- Area Control here --> 
     </uC:AreaDuree> 

     <uC:Area4 Grid.Row="1" Grid.Column="0"> 
      <!-- Area Control here --> 
     </uC:Area4> 

     <uC:Area3 Grid.RowSpan="2" Grid.Column="1"> 
      <!-- Area Control here --> 
     </uC:Area3>       

    </Grid> 

</Grid> 
+0

Sí, eso sería genial. Edité la pregunta para señalar que # 2 podría usarse en otro lugar. – PBelanger

+0

@PBelanger está bien, pero eso solo significa que sus controles de usuario deben estar encapsulados para que pueda cambiar sus respectivos diseños. Tener la parte inferior de Area2 como su propio control le permite colocarlo donde quiera en cualquier cantidad de esquemas de diseño. – Joseph

1

le sugiero que para dividir su control n ° 2 en 3 o 4 control de usuario más específico. Luego carga # 2, # 3, # 4 dentro de un WrapPanel. Compruebe esto link: Layout of UserControl para implementar una estrategia de arreglos y medidas del panel de envoltura inteligente.

1

Para mí, para simplificar la vida de su diseñador, le sugiero la solución de ContentControl.

De esta manera, su diseñador puede agregar fácilmente sus controles y para usted, simplemente asegúrese de que su Usercontrol # 2 sea lo suficientemente inteligente como para que su diseño sea el correcto.

-1

Puede pensar en tener # 3 y # 4 como parte del control de usuario # 2, entonces las cosas simplifican el diseño. Una cuadrícula de nivel superior establece # 1 y # 2

Consulte el diseño del segundo control de usuario. Y todo cuadriculado con * tamaño para que se ajuste el tamaño de acuerdo con el tamaño de la ventana.

alt text http://img5.imageshack.us/img5/4419/40506576.jpg

+0

Si hizo la pregunta, probablemente sea porque necesita usar el UserControl solo. La pregunta es: "¿cómo mover/cambiar el tamaño automáticamente UserControl/Panel en tiempo de ejecución según el contexto?", NO cómo hacerlo de otra manera. –

+0

Sí, pero la sugerencia es aún mejor que nada ... – esylvestre

+0

No sé por qué votas así? La solución es exactamente similar a lo que @Joseph agregó XAML para. El mío es solo representación visual en el mismo –

1

estoy todavía sorprende que nadie ha sugerido el uso de un FlowDocument real para diseñar la interfaz de usuario.

He usado FlowDocument antes para lograr arreglos complejos. Funciona bastante bien, excepto que parte de la herencia de propiedad está bloqueada (TextElement.FontSize, por ejemplo). Esto no es difícil de evitar.

En su caso, simplemente divida # 2 en un UserControl por sección, y dentro de su FlowDocument, use InlineUIContainer para envolver cada sección.

<Window> 
    <DockPanel> 
    ... toolbars, etc ... 

    <FlowDocumentScrollViewer ...> 
     <FlowDocument> 
     ... 
     <InlineUIContainer> 
      <my:PartialNumberTwo DataContext="{Binding ...}" /> 
     </InlineUIContainer> 
     ... 

Por supuesto que hay límites para lo que FlowDocument puede hacer, por lo que puede no funcionar para su escenario.

Una opción extremadamente flexible es crear un panel personalizado que establezca sus elementos secundarios en un estilo WrapPanel, pero ajusta rectángulos y, antes de que comience, marca cualquier área superpuesta por los propios hermanos del panel como no disponible.

Tal un panel sería utilizado como esto:

<Grid ...> 
    ... RowDefinitions, ColumnDefinitions ... 

    <panels:WrapIntoRemainingSpacePanel RowSpan="4" ColumnSpan="3"> <!-- fill whole grid --> 
    <my:Control2Part1 /> 
    <my:Control2Part2 /> 
    <my:Control2Part3 /> 
    <my:Control2Part4 /> 
</panels:WrapIntoRemainingSpacePanel> 

<my:Control1 Grid.Row="0" Grid.ColumnSpan="3" /> 
<my:Control3 Grid.Row="2" Grid.Column="2" Grid.ColumnSpan="2" /> 
<my:Control4 Grid.Row="3" Grid.RowSpan="2" /> 

Este panel se llevaría a cabo como sigue:

  1. En ArrangeOverride, programar una devolución de llamada Dispatcher.BeginInvoke para hacer el organización real e informe tamaño completo usado
  2. En la devolución de llamada, obtenga rectángulos que representen todos los límites de mis hermanos g cuadros en el espacio de coordenadas de mis padres.
  3. Ordenar coordenadas Y (arriba y abajo) de todos los rectángulos
  4. Coloque cada niño encontrando la primera coordenada Y en la lista ordenada en la que hay espacio horizontal en alguna parte para los contenidos y colóquela lo más a la izquierda posible VisualTransform
  5. Seguir los hermanos por los cambios, si los hay InvalidateArrange llamada()
0

Creo que es una cuadrícula sencilla, el 'truco' es que es perfectamente posible tener un control cubierta otro - WPF siempre hacerlos en el mismo orden:

Utilicé Height = "Auto" para todas las filas de la grilla, dependiendo de cómo estén configurados los controles del usuario, es posible que deba especificar una altura real para que se alineen correctamente.

<Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="Auto"/> 
     <RowDefinition Height="Auto"/> 
     <RowDefinition Height="Auto"/> 
     <RowDefinition Height="Auto"/> 
    </Grid.RowDefinitions> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="*"/> 
     <ColumnDefinition Width="Auto"/> 
    </Grid.ColumnDefinitions> 
    <uc:UserControl1 Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2"/> 
    <uc:UserControl2 Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Grid.RowSpan="2"/> 
    <uc:UserControl3 Grid.Row="2" Grid.Column="1" Grid.RowSpan="2"/> 
    <uc:UserControl4 Grid.Row="3" Grid.Column="0"/> 
<Grid> 
0

Es 1 cuadrícula grande, con 3 filas y 2 columnas. Cada zona de esa cuadrícula contiene una cuadrícula capaz de recibir los controles de tus usuarios. Entonces, la cuadrícula número 3 solo necesita obtener su margen superior establecido en -75. Solapará la grilla número 2 si se baja en la xaml. Entonces solo necesita bloquear sus columnas y filas dependiendo de cómo quiera que reaccione.

<Grid x:Name="LayoutRoot"> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="0.55*"/> 
     <ColumnDefinition Width="0.45*"/> 
    </Grid.ColumnDefinitions> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="0.363*"/> 
     <RowDefinition Height="0.369*"/> 
     <RowDefinition Height="0.268*"/> 
    </Grid.RowDefinitions> 
    <Grid Grid.ColumnSpan="2" Background="#FF48C5D0"/> 
    <Grid Margin="1,0,0,0" Grid.ColumnSpan="2" Grid.Row="1" Background="#FFD2A268"/> 
    <Grid Margin="1,0,0,0" Grid.Row="2" Background="#FFB7F075"/> 
    <Grid Grid.Column="1" Grid.Row="2" Background="#FFB129EC" Margin="0,-75,0,0"/> 
</Grid> 

Martin Lamontagne

Cuestiones relacionadas