Open Nils-Berghs opened 3 years ago
Can you elaborate on what the problem with recognizing access key or the use case for disabling it on a label is?
@miloush An underscore in a text is quite common, not on a descriptive label of course, but on text loaded from other system, file names that you want to display, product codes,...
The RecognizesAccessKey property in the label cause the text to be displayed incorrectly (the first underscore vanishes). This also happens if there is no 'Target' element assigned to the label (so the mnemmonic doesn't even work, nor is the next letter in the label underlined). The workarounds above are just that 'work arounds' no solutions.
Recently I had an application where the 'Material Design in Xaml' UI framework is used. I created an application wide style for labels based on the label style in that library. Just a basedOn with a 'Margin property' for some white space. All good until one of the text bound to a label had an underscore
I tried the Textblock solution with an application wide style for the margin, but this impacted, listview, dropdown,.... (as they all use text blocks internally). So I had to fallback to an explicit style on TextBlock an apply it to all textblocks that might have an underscore in them (read all dynamic texts)
Overriding the default label style would also be a bad solution, I would have to copy the entire style from the library change the Recognizes Access Key property and apply that as the application wide label style. Until the style in the library is updated....
As for adding an extra underscore, lets not even consider that (the viewmodel should not occupy itself with fixing limitation in the UI).
As for the solution I implemented, another approach would be to have the 'RecognizesAccessKey' be read only and have it as 'false' if the Target is null (but I think the risk for backward compatibility issues is higer).
I'm not the first one having this issue: https://stackoverflow.com/questions/9684619/label-doesnt-display-character https://social.msdn.microsoft.com/Forums/vstudio/en-US/13a20286-1875-40d1-886f-3febbc139b1d/underscore-character-in-filename-not-showing?forum=wpf
As a final note: Its 2020, not 19XX we have mice, precision touchpads, touchscreens, voice control,.... mnemonics are really not important any more.
As a final final note: A 'feature' that can't be turned off is always a bug' (this problem is a typical example of a violation of that rule)
Thank you for the explanation.
An underscore in a text is quite common, not on a descriptive label of course
That is what I was trying to point out, Label
does not seem to be the correct control for your use case.
I tried the Textblock solution with an application wide style for the margin, but this impacted, listview, dropdown
Style can be scoped to any element and its children by defining it in the element's resources, it doesn't have to be global. Also, if you are dynamically generating these controls, an explicit style reference shouldn't be a problem in the item template, or put the TextBlock
s in a container that can provide the margin instead.
Overriding the default label style would also be a bad solution, I would have to copy the entire style from the library change the Recognizes Access Key property and apply that as the application wide label style
I don't understand why this is bad, you are saying that overriding a style is a bad solution, because you would have to override a style.
If you want to force the Label not to work as a label, overriding its template is a fair and natural way to go, the same way if you wanted a Button not to work as a button. The template for label is not even that complicated.
the viewmodel should not occupy itself with fixing limitation in the UI
My understanding is that the sole purpose of viewmodel is to prepare data for presentation in UI, and this would definitely fit its job.
mnemonics are really not important any more
Please note that mnemonics are an accessibility option. They may be not important to you but there are people who depend on them. I would encourage everyone to make their applications keyboard-only accessible.
A 'feature' that can't be turned off is always a bug'
My problem with this issue is that this is not a feature that can't be turned off - showing accelerators (and allowing focusing the target element) is the only reason for existence of the Label
control, see the documentation. You can turn the feature off by using either TextBlock
or ContentPresenter
. It's similar to suggesting that it is a bug that you cannot turn off the "linking feature" of a hyperlink.
I would like to contradict some stuff:
Style can be scoped to any element and its children by defining it in the element's resources, it doesn't have to be global. Also, if you are dynamically generating these controls, an explicit style reference shouldn't be a problem in the item template, or put the TextBlocks in a container that can provide the margin instead
Of course it can but for my application that would mean: apply an explicit style to every textblock. As for putting the texblock in a container that provides margins, that would mean and extra canvas for every textblock in a grid.
you are saying that overriding a style is a bad solution, because you would have to override a style.
I didn't express myselft correctly, I would not be 'Overwriting' the style I would be duplicating it (copying it, put that value to false). And so with every update of the UI framework you would have to check/update your duplicated style to keep it in sync with the original one.
My understanding is that the sole purpose of viewmodel is to prepare data for presentation in UI
Yes but the viewmodel should not really know which UI (Forms, WPF, UWP,...) and the View sole purpose would be showing the data presented by it by the view model, not modifying it.
Please note that mnemonics are an accessibility option. They may be not important to you but there are people who depend on them. I would encourage everyone to make their applications keyboard-only accessible.
I never said that my applications are not keyboard accessible, I've known people with visual and motoric disabilities use magnifiers, color adjustments, keyboard shortcuts, tab keys, frequently (not mnemonics though). But I have never ever seen anyone use a mnemonic to focus a field that just doesn't exist. (If the underscore would not disappear if the target was null there would be no issue
My problem with this issue is that this is not a feature that can't be turned off - showing accelerators (and allowing focusing the target element) is the only reason for existence of the Label control
If this is true, than where are the counter parts for radio buttons, and other controls that suffer from the same bug?
If this question pops up on fora for a decade, why is it so hard to admit that this really is an issue? Especially since the solution is this simple? (And fixed by the community)
I have never ever seen anyone use a mnemonic to focus a field that just doesn't exist.
I am probably just rephrasing myself, but if you don't have a field to focus then don't use a label whose purpose is to focus a field.
The SO answer has the same comment: Don't put it in a control that has other uses besides just displaying text. Or escape meta-characters.
There seems to be a confusion for people coming from Windows Forms, where there is only a control called Label
that can have access keys turned on and off. Developers then come to WPF, see a Label
and want to use it the same way, bind it to show file names or something, but that functionality is covered by TextBlock
. WPF was designed differently, with separate control for displaying text and separate control for accessing other elements. I believe that is a better design, and doing what you are proposing would revert it and encourage wrong practice.
where are the counter parts for radio buttons, and other controls that suffer
Radio button is a field itself focusable by keyboard by definition.
Both Label
and RadioButton
are content controls. If you really want, you can use TextBlock
inside them:
<Label>
<TextBlock Text="{Binding ...}" />
</Label>
This also happens to be mentioned in the SO question.
since the solution is this simple? (And fixed by the community)
Simple solution does not necessarily mean a good problem to solve. Can you share some code from an application where you are hitting this problem?
The styles
<!-- default style for label-->
<Style TargetType="{x:Type Label}" BasedOn="{StaticResource MaterialDesignLabel}">
<Setter Property="Margin" Value="8"/>
<Setter Property="VerticalAlignment" Value="Center"/>
</Style>
<!-- Sometimes we cannot use label because the recognise access key is hardcoded
We cannot edit de default textblock style because this has huge impact as texblocks
are used within other controls. So this is an explicit style.
The button textblock looks most similar to label
-->
<Style TargetType="{x:Type TextBlock}" BasedOn="{StaticResource MaterialDesignButtonTextBlock}"
x:Key="LabelReplacement">
<Setter Property="Margin" Value="8"/>
<Setter Property="VerticalAlignment" Value="Center"/>
</Style>
The 'test application' (I'v added the green background to the labels and textboxes to show there size and position)
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Label Background="green" Content="Text_with_underscore"/>
<TextBlock Background="green" Text="Text_with_underscore" Grid.Row="1"/>
<TextBlock Style="{StaticResource LabelReplacement}" Background="green" Text="Text_with_underscore" Grid.Row="2"/>
<ComboBox Grid.Row="3">
<ComboBoxItem Content="Item 1"/>
<ComboBoxItem Content="Item 2"/>
<ComboBoxItem Content="Item 3"/>
</ComboBox>
</Grid>
The result:
Now lets add and implicit style for the textblock (equal to the LabelReplacement style).
The result (note the combobox items...):
So should I just use explicit style all over the place, in every application, or just give up on WPF.
So should I just use explicit style all over the place, in every application, or just give up on WPF.
There is no question about repro steps, I was asking for an example from a real application so that we can answer that question and suggest what the solution should be.
But in general yes, if you are only using Label
for its padding and the control is not created as part of ItemsControl
, then an explicit style sounds appropriate.
The "RecognizesAccessKey" of the content presenter of the default label style is hard coded to true (and has been for many years). As a result the first underscore of a label disappears (I have ran into this problem more than I have seen users actually use a mnemmonic).
Multiple work arounds for that problem exist: