Colocación emergente de WPF ComboBox: inferior y alineado al borde derecho
drop-down-menu placement (4)
Estoy tratando de 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
lugar del borde izquierdo.
Cómo se ve un ComboBox
normal, usando PlacementMode="Bottom"
:
Lo que quiero:
Intenté jugar con la propiedad Popup.PlacementMode
en la plantilla de mi ComboBox
, pero ninguno de los valores posibles parece hacer lo que quiero. ¿Hay una manera simple de hacerlo, preferiblemente en XAML puro?
¿Puede alguien publicar el código xaml completo 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 algunos trabajos y pruebas he encontrado una buena solución ...
<ComboBox.Style>
<Style TargetType="ComboBox" >
<Setter Property="Popup.FlowDirection" Value="RightToLeft"/>
</Style>
</ComboBox.Style>
Cuando abrí Expression Blend, encontré la solución en unos segundos:
<Popup Placement="Left" VerticalOffset="{TemplateBinding ActualHeight}"
HorizontalOffset="{TemplateBinding ActualWidth}"
A veces esta aplicación es más útil que escribir xaml con las manos, pero no tan a menudo.
Es un poco hacky, pero funciona. Solo tienes que cambiar el estilo de 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>
La ventana emergente HorizontalOffset solo tiene que obtener el valor de PopupContent.ActualWidth-PlacementTarget.ActualWidth. Para obtener ese valor utilicé este truco de Charles Petzold .
Yo usaría el modo de colocación "Personalizado" para el PopUp y declararía una devolución de llamada para colocar el control emergente en la posición correcta, como se muestra aquí: Colocación del menú desplegable WPF ComboBox DropDown
Vea si un ejemplo aquí funcionaría 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) } };
}
}
Espero que esto ayude, saludos.