Всплывающие координаты в шаблоне ComboBox? - PullRequest
0 голосов
/ 19 июля 2011

Я пытаюсь создать ComboBox, где DropDown или Popup выровнены по правому краю, где недостаточно места с правой стороны ComboBox.

Я могу настроить выравнивание по правому краю, установив для FlowDirection значение RightToLeft, но мне нужно знать, когда выравнивать по правому краю. Поэтому я пытаюсь вычислить правый край всплывающего окна, используя его X-координату (относительно RootVisual) плюс его ширину. Если значение его правого края больше ширины RootVisual, то ComboBox нужно выровнять по правому краю, это Popup или DropDown.

Теперь моя проблема в том, что мне кажется, что Popup наследует координаты ComboBox. Почему я получаю неправильные координаты для всплывающего окна? Это потому, что Popup содержится внутри шаблона для ComboBox? Вот мой пример кода ...

Упрощенный шаблон ComboBox ...

<Style TargetType="local:CustomComboBox">
    <Setter Property="Padding" Value="6,2,25,2"/>
    <Setter Property="Background" Value="#FF1F3B53"/>
    <Setter Property="HorizontalContentAlignment" Value="Left"/>
    <Setter Property="BorderThickness" Value="1"/>
    <Setter Property="TabNavigation" Value="Once"/>
    <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
    <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
    <Setter Property="BorderBrush">
        <Setter.Value>
            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                <GradientStop Color="#FFA3AEB9" Offset="0"/>
                <GradientStop Color="#FF8399A9" Offset="0.375"/>
                <GradientStop Color="#FF718597" Offset="0.375"/>
                <GradientStop Color="#FF617584" Offset="1"/>
            </LinearGradientBrush>
        </Setter.Value>
    </Setter>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="local:CustomComboBox">
                <Grid>
                    <Border x:Name="ContentPresenterBorder">
                        <Grid>
                            <ToggleButton x:Name="DropDownToggle" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" HorizontalAlignment="Stretch" HorizontalContentAlignment="Right" Margin="0" Style="{StaticResource comboToggleStyle}" VerticalAlignment="Stretch">
                                <Path x:Name="BtnArrow" Data="F1 M 301.14,-189.041L 311.57,-189.041L 306.355,-182.942L 301.14,-189.041 Z " HorizontalAlignment="Right" Height="4" Margin="0,0,6,0" Stretch="Uniform" Width="8">
                                    <Path.Fill>
                                        <SolidColorBrush x:Name="BtnArrowColor" Color="#FF333333"/>
                                    </Path.Fill>
                                </Path>
                            </ToggleButton>
                            <ContentPresenter x:Name="ContentPresenter" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
                                <TextBlock Text=" "/>
                            </ContentPresenter>
                        </Grid>
                    </Border>
                    <Popup x:Name="Popup">
                        <Border x:Name="PopupBorder" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="3" HorizontalAlignment="Stretch" Height="Auto">
                            <Border.Background>
                                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                                    <GradientStop Color="#FFFFFFFF" Offset="0"/>
                                    <GradientStop Color="#FFFEFEFE" Offset="1"/>
                                </LinearGradientBrush>
                            </Border.Background>
                            <ScrollViewer x:Name="ScrollViewer" BorderThickness="0" Padding="1">
                                <ItemsPresenter/>
                            </ScrollViewer>
                        </Border>
                    </Popup>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Код контроля за ...

public class CustomComboBox : ComboBox
{
    private Popup _popup;
    private ScrollViewer _scrollViewer;

    public CustomComboBox()
    {
        this.DefaultStyleKey = typeof(CustomComboBox);
    }

    protected override void OnDropDownOpened(EventArgs e)
    {
        GeneralTransform gt = _popup.TransformToVisual(App.Current.RootVisual as UIElement);
        Point popupOffset = gt.Transform(new Point(0, 0));

        double popupRightEdge = popupOffset.X + _popup.ActualWidth;

        double appRightEdge = (App.Current.RootVisual as FrameworkElement).ActualWidth;

        if (popupRightEdge > appRightEdge)
        {
            _popup.FlowDirection = FlowDirection.RightToLeft;
            _scrollViewer.FlowDirection = FlowDirection.LeftToRight;
        }

        base.OnDropDownOpened(e);
    }

    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();

        _popup = GetTemplateChild("Popup") as Popup;
        _scrollViewer = GetTemplateChild("ScrollViewer") as ScrollViewer;
    }
}

1 Ответ

0 голосов
/ 26 октября 2011

ValidationErrorElement в ControlTemplate ComboBox вызвал выравнивание всплывающего окна по правому краю, а не по правому краю фактического ComboBox. Я рекомендую изменить имя элемента управления Popup, которое называется «Popup», на что-то вроде «DropDownPopup» в ControlTemplate для ComboBox, а затем привязать свойство IsOpen вашего Popup к свойству IsChecked объекта ToggleButton. Всплывающее окно является частью управления ComboBox, и я подозреваю, что к нему подключен некоторый код, чтобы заставить его вести себя так, как он работает.

Также в Virtualization StackPanel мы использовали повышенную производительность, но создали другое странное поведение. Установка фиксированной ширины на виртуализированной StackPanel исправила это. Установка фиксированной ширины во всплывающем окне также исправляет это.

...