Неправильный фокус при попытке щелкнуть внутри RadComboBox

Итак, у меня есть RadCombobBox, который сильно отредактирован, чтобы иметь список опций, где 1 из опций может быть полем ввода. Существуют различные типы полей ввода, из которых вы можете выбирать, но у меня проблема с целочисленным полем ввода. Также есть поле с полем ввода текста, которое не показывает проблем.

Combobox выглядит так:

Текст нидерландский (не обращайте на это внимания) под опциями текста есть предустановленное значение, идея здесь в том, что вы можете либо выбрать предустановленную настройку (которая соответствует целочисленному значению), либо вы можете ввести собственное значение.

Что происходит, когда я пытаюсь нажать на разные места (последнее очень своеобразно):

  • Если я пытаюсь нажать на поле ввода (которое выделено серым цветом), оно выбирает его и закрывает поле со списком (это не то, что я хочу).
  • Если я попытаюсь нажать на стрелки в правой части поля со списком, это изменит значение.
  • Если я прокручиваю мышью, это меняет значение.
  • Если я удерживаю мышь в поле ввода, я могу ввести значение, которое я хочу.
  • Если я сначала нажимаю на кнопки сбоку, а затем нажимаю внутри поля ввода, я могу изменить значение.

Я хочу щелкнуть по полю ввода и иметь возможность редактировать значение внутри, а когда я закончу, нажмите клавишу ввода (или вне поля со списком), чтобы закрыть его.

Каким-то образом фокус или что-то (я не уверен на 100%), кажется, подводит меня. Вот код xaml для IntegerDataTemplate:

Целочисленный селектор

<Style x:Key="NumericUpDownStyle" TargetType="{x:Type telerik:RadNumericUpDown}">
    <Style.Triggers>
        <Trigger Property="IsEnabled" Value="False">
            <Setter Property="BorderBrush" Value="{StaticResource AccentBrush}" />
        </Trigger>
        <Trigger Property="IsEditable" Value="False">
            <Setter Property="SmallChange" Value="0" />
            <Setter Property="LargeChange" Value="0" />
        </Trigger>
    </Style.Triggers>
</Style>

<!--  Integer editor  -->
<DataTemplate x:Key="IntegerDataTemplate">
    <telerik:RadNumericUpDown x:Name="NumericUpDown"
                              Width="{Binding Path=ActualWidth,
                                              ElementName=Editor}"
                              MaxWidth="{Binding Path=ActualWidth,
                                                 ElementName=Editor,
                                                 Converter={StaticResource WidthToWidthConverter}}"
                              HorizontalContentAlignment="Left"
                              Background="Transparent"
                              FontFamily="{telerik:Windows8Resource ResourceKey=FontFamilyStrong}"
                              IsInteger="True"
                              Style="{StaticResource NumericUpDownStyle}"
                              UpdateValueEvent="PropertyChanged"
                              Value="{Binding Path=Value,
                                              UpdateSourceTrigger=PropertyChanged,
                                              NotifyOnSourceUpdated=True}">
        <telerik:RadNumericUpDown.NumberFormatInfo>
            <globalization:NumberFormatInfo NumberGroupSeparator="" />
        </telerik:RadNumericUpDown.NumberFormatInfo>
    </telerik:RadNumericUpDown>
</DataTemplate>

<!--  Integer as Option  -->
<DataTemplate x:Key="OptionsDataTemplate">
    <TextBlock Height="20" Text="{Binding Converter={StaticResource IntegerSelectorObjectToStringConverter}}" />
</DataTemplate>

<local:SelectorTypeTemplateSelector x:Key="IntegerTemplateSelector"
                                    OptionsDataTemplate="{StaticResource OptionsDataTemplate}"
                                    SelectorDataTemplate="{StaticResource IntegerDataTemplate}" />

Где-то это идет не так, есть ли кто-нибудь, кто может указать мне правильный путь, чтобы исправить это (обходной путь также будет хорошо).

Я хотел бы добавить, что у меня есть тот же код, но с текстовым полем, которое работает правильно, я добавил код ниже для сравнения, но я не смог найти существенную разницу.

Селектор текста (который на самом деле работает правильно)

<Style x:Key="TextBoxStyle" TargetType="{x:Type telerik:RadWatermarkTextBox}">
    <Setter Property="BorderBrush" Value="{StaticResource BasicBrush}" />
    <Setter Property="FontFamily" Value="{telerik:Windows8Resource ResourceKey=FontFamilyStrong}" />
    <Setter Property="Padding" Value="2,2,0,0" />
    <Setter Property="Validation.ErrorTemplate" Value="{StaticResource ErrorTemplate}" />
    <Setter Property="telerik:RadWatermarkTextBox.WatermarkTemplate">
        <Setter.Value>
            <DataTemplate>
                <TextBlock Margin="2,3,0,0"
                           FontFamily="Segoe UI"
                           FontStyle="Italic"
                           Foreground="{StaticResource WaterMarkBrushNoOpacity}"
                           Padding="0,-2,0,0"
                           Text="{Binding}" />
            </DataTemplate>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <Trigger Property="IsEnabled" Value="False">
            <Setter Property="BorderBrush" Value="{StaticResource AccentBrush}" />
        </Trigger>
        <Trigger Property="IsReadOnly" Value="True">
            <Setter Property="BorderBrush" Value="{StaticResource MarkerDisabledBrush}" />
        </Trigger>
    </Style.Triggers>
</Style>

<!--  String editor  -->
<DataTemplate x:Key="StringDataTemplate">
    <telerik:RadWatermarkTextBox x:Name="WatermarkTextBox"
                                 HorizontalAlignment="Stretch"
                                 HorizontalContentAlignment="Stretch"
                                 VerticalContentAlignment="Top"
                                 Background="Transparent"
                                 BorderThickness="1"
                                 Style="{StaticResource TextBoxStyle}"
                                 Text="{Binding Path=Value,
                                                UpdateSourceTrigger=PropertyChanged,
                                                NotifyOnSourceUpdated=True}" />
</DataTemplate>

<!--  String as Option  -->
<DataTemplate x:Key="OptionsDataTemplate">
    <TextBlock Height="20" Text="{Binding Converter={StaticResource StringSelectorObjectToStringConverter}}" />
</DataTemplate>

<local:SelectorTypeTemplateSelector x:Key="StringTemplateSelector"
                                    OptionsDataTemplate="{StaticResource OptionsDataTemplate}"
                                    SelectorDataTemplate="{StaticResource StringDataTemplate}" />

2 ответа

Решение

Решение было довольно простым, я пытался исправить его с помощью предпросмотра мышью вниз, но мне нужно было сделать предпросмотр мышью вверх, добавив: PreviewMouseLeftButtonUp="EditorPreviewMouseLeftButtonUp" в xaml, который сделал код RadComboBox следующим образом:

telerik:RadComboBox x:Name="Editor"
    BorderThickness="0"
    FontWeight="SemiBold"
    ItemTemplateSelector="{StaticResource IntegerTemplateSelector}"
    PreviewMouseLeftButtonUp="EditorPreviewMouseLeftButtonUp"
                             SelectionBoxTemplate="{StaticResource SelectionboxTemplate}"
    Validation.ErrorTemplate="{StaticResource ErrorTemplate}" />

Код выглядит так:

private void EditorPreviewMouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
    var originalSource = e.OriginalSource as FrameworkElement;
    if ((originalSource != null) && (originalSource.ParentOfType<TextBox>() != null))
    {
        e.Handled = true;
    }
}

MouseUp - это когда вызывается событие изменения выбора, которое вызывает закрытие комбинированного списка, сообщая, что событие завершено до того, как это произойдет, и оно не закроет комбинированный список. Все, что вам теперь нужно сделать, это нажать клавишу ввода после того, как вы изменили значение, и оно будет правильно выбрано и обновлено.

Действительно трудно понять, что происходит, не перебирая все кусочки (например, стиль + код RadComboBox), но было бы естественно предположить, что это как-то связано с автоматическим закрытием выпадающего меню, когда оно теряет фокус особенно если учесть, что стандартный WPF ComboBox имеет состояние FocusedDropDown, которое открывает всплывающее окно.

Вы можете попробовать скопировать RadComboBox, импортировав стиль из Telerik и расширив код до нового класса (и изменив стиль с помощью импортированного шаблона). Таким образом, вы можете переопределить методы и присоединиться к событиям (например, Got/LostFocus), а также поиграть с шаблоном, чтобы посмотреть, сможете ли вы настроить его под свои нужды.

Однако попытка втиснуть такое поведение в существующие элементы управления, просто потому, что можно изменить стиль шаблонов, часто просто приводит к большому горе (и потраченным часам).

У меня есть ощущение, что было бы проще создать NumericRadComboBox, в котором числовые значения вверх / вниз встроены в сам комбинированный список. Таким образом, вы переустанавливаете RadComboBox так, чтобы рядом со стрелкой выпадающего меню располагались цифровые кнопки вверх / вниз, и вручную применяете режим увеличения / уменьшения.

Другие вопросы по тегам