2011-03-17 12 views
18

Estoy intentando crear un ComboBox con una alineación desplegable no estándar. Básicamente, quiero que el menú desplegable esté debajo del ComboBox, pero alineado con el borde derecho del ComboBox en lugar del borde izquierdo.Ubicación emergente de WPF ComboBox: Inferior y alineado con el borde derecho

Lo normal ComboBox parece, utilizando PlacementMode="Bottom":

combo box aligned to the left

lo que quiero:

combobox aligned to the right

Traté de jugar con la propiedad Popup.PlacementMode en la plantilla de mi ComboBox , pero ninguno de los posibles valores parece hacer lo que quiero. ¿Hay una manera simple de hacerlo, preferiblemente en XAML puro?

Respuesta

37

Cuando abrí Expression Blend, que han llegado con la solución dentro de unos pocos segundos:

<Popup Placement="Left" VerticalOffset="{TemplateBinding ActualHeight}" 
     HorizontalOffset="{TemplateBinding ActualWidth}" 

A veces esta aplicación es más útil que la escritura xaml por las manos, pero no tan a menudo. enter image description here

+0

Esto no hace lo que estoy pidiendo en absoluto ... mira las imágenes en mi pregunta –

+1

@Thomas Levesque Ok, adjunté la captura de pantalla de mi aplicación. Lo siento, pero no puedo ver una diferencia entre tu segundo combobox y el mío. – vorrtex

+0

lo siento, mi error ... Me había perdido la parte Placement = "Left", funciona perfectamente ahora. Excelente respuesta, gracias! –

2

es un poco hacky, pero funciona. solo tienes que cambiar el estilo de la combobox.

<Grid Height="40"> 
     <Grid HorizontalAlignment="Center" VerticalAlignment="Center"> 
      <FrameworkElement Name="dummy" Visibility="Collapsed"> 
       <FrameworkElement.RenderTransform> 
        <TransformGroup x:Name="xformgrp"> 
         <TranslateTransform X="{Binding ElementName=PopupContent, Path=ActualWidth}" /> 
         <ScaleTransform ScaleX="-1" /> 
         <TranslateTransform X="{Binding ElementName=chk, Path=ActualWidth}" /> 
        </TransformGroup> 
       </FrameworkElement.RenderTransform> 
      </FrameworkElement> 
      <CheckBox Name="chk" HorizontalAlignment="Center">checkthisout</CheckBox> 
      <Popup IsOpen="{Binding IsChecked, ElementName=chk}" PlacementTarget="{Binding ElementName=chk}" Placement="Bottom" HorizontalOffset="{Binding ElementName=dummy, Path=RenderTransform.Value.OffsetX}"> 
       <TextBlock Name="PopupContent" Foreground="Yellow" Background="Blue">yeah long popupcontent</TextBlock> 
      </Popup> 
     </Grid>    
    </Grid> 

El popups HorizontalOffset sólo tiene que obtener el valor de PopupContent.ActualWidth-PlacementTarget.ActualWidth. Para obtener ese valor, utilicé this trick from Charles Petzold.

+0

Gracias, muy inteligente ... pero también bastante aterrador;) –

+0

@Thomas si crees que da miedo ... Es una broma, dijiste, no querías ningún código. Si permite código subyacente, simplemente cree un enlace múltiple con un convertidor que haga PopupContent.ActualWidth-PlacementTarget.ActualWidth. De esta forma, su xaml no se ve tan atemorizante, ya que el elemento dummy wohle se elimina. –

+0

un convertidor no cuenta como código subyacente;). De todos modos, quería la solución más simple posible, y la respuesta de vorrtex es de lejos la más simple y es pura XAML, así que la acepté –

4

me gustaría utilizar el placementmode "Custom" para el emergente y declarar una devolución de llamada para colocar el control emergente en la posición correcta, como se muestra aquí: WPF ComboBox DropDown Placement

A ver si un ejemplo aquí sería trabajar para usted :

public class TestComboBox : ComboBox 
{ 
    public override void OnApplyTemplate() 
    { 
     base.OnApplyTemplate(); 

     var popup = (Popup)Template.FindName("PART_Popup", this); 
     popup.Placement = PlacementMode.Custom; 
     popup.CustomPopupPlacementCallback += (Size popupSize, Size targetSize, Point offset) => 
      new[] { new CustomPopupPlacement() { Point = new Point (targetSize.Width-popupSize.Width, targetSize.Height) } }; 
    } 
} 

esperanza que esta ayuda, que se refiere a

+0

Gracias por ¡Tu respuesta! Pensé en eso también, pero prefiero una solución XAML pura, y la respuesta de vorrtex se ajusta perfectamente a la factura –

+0

¡buena respuesta! e asiest para implementar –

4

Puede alguien publicar el código XAML completa por favor?

He intentado lo siguiente:

<ComboBox Grid.Column="1" Height="24" Width="20" HorizontalAlignment="Right" 
       VerticalAlignment="Top"     
       Name="comboBox2" 
       ItemsSource="{Binding Source={StaticResource FilterTypes}}" 
       SelectedValue="{Binding Path=SelectedType, Mode=TwoWay}" > 

     <ComboBox.Template> 
      <ControlTemplate> 
       <Popup Placement="Left" VerticalOffset="{TemplateBinding ActualHeight}" 
         HorizontalOffset="{TemplateBinding ActualWidth}" /> 
      </ControlTemplate> 
     </ComboBox.Template> 
    </ComboBox> 

... después de algún trabajo y pruebas que he encontrado una buena solución ...

 <ComboBox.Style> 
      <Style TargetType="ComboBox" >          
       <Setter Property="Popup.FlowDirection" Value="RightToLeft"/>     
      </Style> 
     </ComboBox.Style>  
+0

solo copie la plantilla ComboBox original y modifique solo la ventana emergente (puede encontrar la plantilla original en [temas predeterminados] (http://archive.msdn.microsoft.com/wpfsamples#themes)) –

+0

@Sascha Krumbein Bienvenido a stackoverflow. Este no es un foro. Si tiene una pregunta específica relacionada con la programación, formule una nueva pregunta. – vidstige

+0

Esta respuesta no parece agregar nada a la respuesta más votada y aceptada, parece ser más una pregunta. Sascha, ¿podrías intentar mejorar la respuesta? – ANeves

Cuestiones relacionadas