2009-02-10 13 views

Respuesta

16

Nota: Asegúrese de revisar Rachel's answer - ella toma esta un paso más en una plantilla genérica


En primer lugar no pierda su tiempo con VerticalAlignment o VerticalContentAlignment (o incluso ControlTemplate). No harán lo que quieran o esperen.

Como se describe en MSDN a BulletDecorator (que es el control que CheckBox y RadioButton utilizan para procesar un botón de radio/comprobación) configurará la posición del icono automáticamente. Usted no tiene ningún control adicional sobre esto:

una bala siempre se alinea con la primera línea de texto cuando el objeto Niño es un objeto de texto. Si el objeto secundario no es un objeto de texto, la viñeta se alinea con el centro del objeto secundario.

A menos que cambie la plantilla de control (innecesario) sólo será capaz de posicionarse en el icono de la radio/verificación en la parte superior si el contenido es texto.

Así que si haces algo como esto no se verá bien porque no podrás mover el ícono sin importar cuántas propiedades VerticalAlignment intentes establecer.

<RadioButton> 
    <StackPanel> 
     <TextBlock Text="First line"/> 
     <TextBlock Text="Something else"/> 
    </StackPanel> 
</RadioButton> 

PERO Afortunadamente, usted puede poner casi cualquier cosa que desee en un TextBlock usando InlineUIContainer. El texto (o contenido) en la primera línea determinará la posición del icono automáticamente. Si quieres algo por debajo de la primera línea que no es de texto, sólo tiene que utilizar <Linebreak/> y luego <InlineUIContainer/>

Aquí hay un ejemplo que tiene un gran tamaño TextBox para mostrar con mayor claridad lo que está pasando.

<RadioButton> 

    <TextBlock VerticalAlignment="Top" TextWrapping="Wrap"> 

     <TextBlock Text="Products with &lt;" VerticalAlignment="Center" Margin="0,0,5,0"/> 

     <InlineUIContainer BaselineAlignment="Center"> 
      <TextBox FontSize="30" Width="25" Text="10" Margin="0,0,5,0"/>   
     </InlineUIContainer> 

     <TextBlock VerticalAlignment="Center" Margin="0,0,5,0"> 
      <Run Text="days" FontWeight="Bold"/> 
      <Run Text="inventory" /> 
     </TextBlock> 

     <LineBreak/>  

     <InlineUIContainer> 
      <StackPanel> 
       <CheckBox Content="Include unsold products" /> 
       <CheckBox Content="Include something else" /> 
      </StackPanel> 
     </InlineUIContainer> 

    </TextBlock> 
</RadioButton> 
+0

Un consejo muy útil. ¡Gracias! –

+0

ja Acabo de notar que tengo VerticalAlignment = "Top" después de haber dicho que no era necesario. Creo que probablemente no está aquí –

+1

El estilo predeterminado de WPF RadioButton ya no usa BulletDecorator en Windows 8 (aero2). Parece que no requiere este truco y puede agregar una Grilla. Todavía necesita este truco en Windows XP (luna). Tal vez Windows 7 (aero) es lo mismo que Windows 8 pero no puedo verificar esto en este momento. – Zodman

2

Anula la plantilla de control para el botón de radio. Aquí está el ejemplo de MSDN Radio Button Control Template Example

Si no desea anular la plantilla Control.Template para el botón de opción, puede convertir el contenido en un TextBlock Envuelto. ver esta muestra

<RadioButton Name="radioButton1"> 
    <TextBlock TextWrapping="Wrap">Here is some multiline text that does some wrapping</TextBlock> 
</RadioButton> 
+0

Tenía la esperanza de hacerlo sin necesidad de anular la plantilla de botón de radio ya que la alineación es lo único que quiero cambiar. –

+0

¿Desea que el botón de opción se sitúe encima del texto o desea que el botón de radio esté al lado del otro con el botón alineado en la parte superior de la fila (como al lado de un párrafo)? – bendewey

+0

Y me gustaría hacerlo también para CheckBoxes, que debería tener la misma solución. –

13

He construido una plantilla relativamente genérico basado en Simon Weaver's answer que se puede utilizar en la mayoría de situaciones sin tener que recordar para personalizar su RadioButton.Content todo el tiempo.

<ControlTemplate x:Key="MultiLineRadioButtonTemplate" TargetType="{x:Type RadioButton}"> 
    <RadioButton IsChecked="{TemplateBinding IsChecked}"> 
     <TextBlock> 
      <LineBreak /> 
      <InlineUIContainer> 
       <ContentPresenter Margin="0,-21,0,8" 
            Content="{TemplateBinding ContentPresenter.Content}" 
            ContentTemplate="{TemplateBinding ContentPresenter.ContentTemplate}"/> 
      </InlineUIContainer> 
     </TextBlock> 
    </RadioButton> 
</ControlTemplate> 

Para explicar cómo funciona la plantilla:

  • El TextBlock está ahí porque por defecto, la bala RadioButton se alinea con la primera línea de texto si el contenido es un objeto de texto (un Label se no funciona)

  • el LineBreak es envolver el contenido a una nueva línea, por lo que se crea la primera línea

  • El InlineUIContainer es por lo que podemos colocar el contenido no textual en un TextBlock

  • El ContentPresenter es mantener el contenido real, y tiene un margen superior negativo para eliminar el espacio dejado por el objeto LineBreak.

Aquí hay algunos contenidos ejemplo:

<StackPanel> 
    <RadioButton Template="{StaticResource MultiLineRadioButtonTemplate}"> 
     <StackPanel> 
      <Label Content="Option 1" /> 
      <StackPanel> 
       <CheckBox Content="Some setting" /> 
       <CheckBox Content="Some other setting" /> 
      </StackPanel> 
     </StackPanel> 
    </RadioButton> 

    <RadioButton Template="{StaticResource MultiLineRadioButtonTemplate}"> 
     <StackPanel> 
      <Label Content="Option 2" /> 
      <DataGrid AutoGenerateColumns="False" Height="100"> 
       <DataGrid.Columns> 
        <DataGridTextColumn Header="Id" /> 
        <DataGridTextColumn Header="Date" /> 
        <DataGridTextColumn Header="Total" /> 
        <DataGridTextColumn Header="Count" /> 
       </DataGrid.Columns> 
      </DataGrid> 
     </StackPanel> 
    </RadioButton> 


    <RadioButton Template="{StaticResource MultiLineRadioButtonTemplate}"> 
     <StackPanel> 
      <Label Content="Option 3" /> 
      <TextBlock TextWrapping="WrapWithOverflow" Margin="2"> 
       Lorem ipsum dolor sit amet, consectetur adipisicing elit, 
       sed do eiusmod tempor incididunt ut labore et dolore magna 
       aliqua. Ut enim ad minim veniam, quis nostrud exercitation 
       ullamco laboris nisi ut aliquip ex ea commodo consequat. 
       Duis aute irure dolor in reprehenderit in voluptate velit 
       esse cillum dolore eu fugiat nulla pariatur. Excepteur sint 
       occaecat cupidatat non proident, sunt in culpa qui officia 
       deserunt mollit anim id est laborum. 
      </TextBlock> 
     </StackPanel> 
    </RadioButton> 
</StackPanel> 

Y como se ve:

enter image description here

La única cosa que realmente no estoy feliz por es el margen superior negativo para el ContentPresenter está codificado, porque si alguna vez cambia el tamaño de la fuente, tiene que ajustar manualmente ese margen.

Probablemente no sería tan difícil construir un convertidor para la propiedad Margin que calcula la altura del salto de línea ({TemplateBinding FontSize}?), O incluso una versión extendida del control RadioButton que tiene este comportamiento por defecto, pero por ahora estoy de acuerdo con la codificación -21 basada en el tamaño de fuente predeterminado de mi aplicación.

Además, es posible que desee añadir un poco de TemplateBindings a la RadioButton en la plantilla si desea heredar otras propiedades de la original RadioButton, como márgenes, rellenos, alineación, etc. Sólo obligado a IsChecked con el propósito de manteniéndolo simple.

+1

Parece que va a ser realmente útil, buen trabajo. –

+0

genial :-) Gracias –

+0

Usando la plantilla de alguna forma se detiene el botón de opción para usar GroupName. Esto significa que en el ejemplo anterior, el usuario puede verificar las tres opciones, lo que significa que ya no es un botón de opción. – redsolo

Cuestiones relacionadas