尝试在 RadComboBox 内部单击时焦点错误
focus is wrong when trying to click inside a RadComboBox
所以我有一个 RadCombBox,它经过大量编辑以包含一个选项列表,其中 1 个选项可以是输入字段。您可以选择不同类型的输入字段,但我对整数输入字段有疑问。还有一个带有文本输入字段,显示没有问题。
组合框如下所示:
文本是荷兰语(不要介意)在文本选项下面有一个预设值,这里的想法是您可以选择一个预设设置(对应于一个整数值)或者您可以输入自己的价值。
当我尝试点击不同的地方时会发生什么(最后一个很奇怪):
- 如果我尝试单击输入框(以灰色突出显示),它会选中它并关闭组合框(这不是我想要的)。
- 如果我尝试单击组合框右侧的箭头,它会更改值。
- 如果我用鼠标滚动,它会更改值。
- 如果我将鼠标放在输入框上,我实际上可以输入我想要的值。
- 如果我先单击侧面的按钮,然后在输入框内单击,我可以编辑该值。
我想要的是单击输入框并能够编辑里面的值,当我完成后按回车键(或组合框外)关闭它。
不知何故,焦点或某事(我不是 100% 确定)似乎让我失望了。
这是 IntegerDataTemplate 的 xaml 代码:
整数选择器
<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}" />
如果不实际摆弄所有的点点滴滴(例如 RadComboBox 样式 + 代码),真的很难知道发生了什么,但很自然地假设这与自动下拉菜单有关失去焦点时关闭,特别是考虑到标准 WPF ComboBox 具有打开弹出窗口的 FocusedDropDown 状态。
您可以尝试通过从 Telerik 导入样式来复制 RadComboBox,并将后面的代码扩展到新的 class(并使用导入的模板重新设置样式)。通过这种方式,您可以覆盖方法并附加到事件(例如 Got/LostFocus),并尝试使用模板以查看是否可以根据您的需要进行调整。
然而,仅仅因为可以重新设计模板样式而试图将这种行为纳入现有控件中,通常只会以很多悲伤(和浪费时间)告终。
我觉得创建一个数字 up/down 嵌入组合框本身的 NumericRadComboBox 会更容易。因此,您重新设置 RadComboBox 的样式,使下拉箭头旁边有数字 up/down 按钮,并手动实现 increment/decrement 行为。
解决方案相当简单,我试图通过按下预览鼠标来修复它,但我需要做的是在预览鼠标上添加: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 是在调用选择更改事件时导致组合框关闭,通过声明事件在此之前完成,它不会关闭组合框。您现在所要做的就是在更改值后按回车键,它将被正确选择和更新。
所以我有一个 RadCombBox,它经过大量编辑以包含一个选项列表,其中 1 个选项可以是输入字段。您可以选择不同类型的输入字段,但我对整数输入字段有疑问。还有一个带有文本输入字段,显示没有问题。
组合框如下所示:
文本是荷兰语(不要介意)在文本选项下面有一个预设值,这里的想法是您可以选择一个预设设置(对应于一个整数值)或者您可以输入自己的价值。
当我尝试点击不同的地方时会发生什么(最后一个很奇怪):
- 如果我尝试单击输入框(以灰色突出显示),它会选中它并关闭组合框(这不是我想要的)。
- 如果我尝试单击组合框右侧的箭头,它会更改值。
- 如果我用鼠标滚动,它会更改值。
- 如果我将鼠标放在输入框上,我实际上可以输入我想要的值。
- 如果我先单击侧面的按钮,然后在输入框内单击,我可以编辑该值。
我想要的是单击输入框并能够编辑里面的值,当我完成后按回车键(或组合框外)关闭它。
不知何故,焦点或某事(我不是 100% 确定)似乎让我失望了。 这是 IntegerDataTemplate 的 xaml 代码:
整数选择器
<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}" />
如果不实际摆弄所有的点点滴滴(例如 RadComboBox 样式 + 代码),真的很难知道发生了什么,但很自然地假设这与自动下拉菜单有关失去焦点时关闭,特别是考虑到标准 WPF ComboBox 具有打开弹出窗口的 FocusedDropDown 状态。
您可以尝试通过从 Telerik 导入样式来复制 RadComboBox,并将后面的代码扩展到新的 class(并使用导入的模板重新设置样式)。通过这种方式,您可以覆盖方法并附加到事件(例如 Got/LostFocus),并尝试使用模板以查看是否可以根据您的需要进行调整。
然而,仅仅因为可以重新设计模板样式而试图将这种行为纳入现有控件中,通常只会以很多悲伤(和浪费时间)告终。
我觉得创建一个数字 up/down 嵌入组合框本身的 NumericRadComboBox 会更容易。因此,您重新设置 RadComboBox 的样式,使下拉箭头旁边有数字 up/down 按钮,并手动实现 increment/decrement 行为。
解决方案相当简单,我试图通过按下预览鼠标来修复它,但我需要做的是在预览鼠标上添加: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 是在调用选择更改事件时导致组合框关闭,通过声明事件在此之前完成,它不会关闭组合框。您现在所要做的就是在更改值后按回车键,它将被正确选择和更新。