64

I am setting the .Content value of a Label to a string that contains underscores; the first underscore is being interpreted as an accelerator key.

Without changing the underlying string (by replacing all _ with __), is there a way to disable the accelerator for Labels?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Richard Morgan
  • 7,601
  • 9
  • 49
  • 86
  • 1
    Is there a reason you want to use a Label as opposed to a TextBlock? – Daniel Jennings Sep 02 '08 at 21:36
  • 1
    Yes - `Label` does a lot more than handle the accelerators. Also applies to other controls (e.g. `GroupBox`) that can't be replaced by a `TextBlock`. – GraemeF Mar 01 '10 at 10:08
  • 1
    this is helpful about this topic: http://stackoverflow.com/questions/10452462/make-a-hotkey-to-focus-a-textbox-in-wpf – Emil Nachev Jan 21 '16 at 07:52

4 Answers4

91

If you use a TextBlock as the Content of the Label, its Text will not absorb underscores.

yota
  • 926
  • 7
  • 3
  • 2
    I just used this approach in my app and it worked like a champ. – RQDQ Jul 09 '10 at 17:36
  • 2
    Does not work if you want to retain an already assigned doubleclick event (TextBlock does not have it) – Hexo Oct 16 '17 at 12:07
35

You could override the RecognizesAccessKey property of the ContentPresenter that is in the default template for the label. For example:

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <Grid>
    <Grid.Resources>
      <Style x:Key="{x:Type Label}" BasedOn="{StaticResource {x:Type Label}}" TargetType="Label">
        <Setter Property="Template">
          <Setter.Value>
            <ControlTemplate TargetType="Label">
              <Border>
                <ContentPresenter
                  HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                  VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                  RecognizesAccessKey="False" />
              </Border>
            </ControlTemplate>
          </Setter.Value>
        </Setter>
      </Style>
    </Grid.Resources>
    <Label>_This is a test</Label>
  </Grid>
</Page>
gav
  • 29,022
  • 23
  • 65
  • 90
denis phillips
  • 12,550
  • 5
  • 33
  • 47
  • Just tried this, doesn't work, actually. Perhaps it does remove access-key binding, but it doesn't prevent the underscore from being removed. – xanadont May 14 '09 at 04:23
  • Just copied the code into Kaxaml and worked. Did you try as is or change it at all? – denis phillips May 14 '09 at 21:18
  • 1
    Works for me, but changes the way a label looks :( – Anders Rune Jensen Mar 19 '10 at 16:07
  • @AndersRuneJensen Try using `BasedOn="{StaticResource {x:Type Label}}"` to keep the styling set in parent resources – gav Nov 17 '11 at 09:15
  • 35
    Am I the only one who's thinking that there's something wrong having to write half a page of XAML just to disable the accelerator key? – TtT23 Jul 10 '13 at 16:32
  • @l46kok most likely not. Reason behind it is WPF will give you a lot out of the box and when you want to change it you need to be very specific. Unlike pesky `WinForms` where everything is in code behind. – XAMlMAX Nov 03 '17 at 11:49
  • 1
    Microsoft's official documentation doesn't show this, but I believe this should actually have ``. Without this, the padding is not incorporated and the visual appearance of the `Label` is different with this template as compared to the default. – Jonathan Gilbert Feb 07 '18 at 23:08
1

Use a <TextBlock> ... </TextBlock> instead of <Label> ... </Label> to print the exact text, which is having underscores.

Martin Backasch
  • 1,829
  • 3
  • 20
  • 30
0

Why not like this?

public partial class LabelEx : Label
    {
        public bool PreventAccessKey { get; set; } = true;

        public LabelEx()
        {
            InitializeComponent();
        }

        public new object Content
        {
            get
            {
                var content = base.Content;
                if (content == null || !(content is string))
                    return content;

                return PreventAccessKey ?
                    (content as string).Replace("__", "_") : content;
            }
            set
            {
                if (value == null || !(value is string))
                {
                    base.Content = value;
                    return;
                }

                base.Content = PreventAccessKey ?
                    (value as string).Replace("_", "__") : value;
            }
        }
    }
  • 2
    This is not goog solution. Sometimes string has more than one underscore and WPF does not display only the first of them. This solution duplicates all underscores and can end up with duplicate underscore displayed. – Gabriel May 11 '20 at 07:59