WPF: как стилизовать или отключить ContextMenu по умолчанию для TextBox

Очевидно, когда пользователи щелкают правой кнопкой мыши в нашем приложении WPF и используют тему Windows Classic, контекстное меню по умолчанию TextBox (которое содержит копирование, вырезание и вставку) имеет черный фон.

Я знаю, что это хорошо работает:

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

  <TextBox ContextMenu="{x:Null}"/>

</Page>

Но это не работает:

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

<Page.Resources>

 <Style x:Key="{x:Type TextBox}" TargetType="{x:Type TextBox}">
   <Setter Property="ContextMenu" Value="{x:Null}"/>
</Style>
</Page.Resources>

  <TextBox/>
</Page> 

Кто-нибудь знает, как стилизовать или отключить ContextMenu по умолчанию для всех текстовых полей в WPF?

Ответов (6)

Решение

Из-за позднего отчета об ошибке мы обнаружили, что мы не можем использовать ApplicationComands Cut Paste and Copy непосредственно в частично доверенном приложении. Таким образом, использование этих команд в любой команде ваших элементов управления при выполнении абсолютно ничего не даст.

Так что, по сути, ответ Брэдса был почти готов, он выглядел правильно, т.е. без черного фона, но не решил проблему.

Мы решили «убрать» меню, основываясь на ответе Брэдса, вот так:

<ContextMenu x:Key="TextBoxContextMenu" Width="0" Height="0" />

И используйте это пустое контекстное меню так:

<Style TargetType="{x:Type TextBox}">
  <Setter Property="ContextMenu" Value="{StaticResource TextBoxContextMenu}" />
</Style>

Странно. ContextMenu="{x:Null}" не помогает.

Однако это действительно так:

<TextBox.ContextMenu>
    <ContextMenu Visibility="Collapsed">
    </ContextMenu>
</TextBox.ContextMenu>

Я всегда использую вот такой способ:

      <TextBox x:Name="MyTextbox">
         <TextBox.ContextMenu>
         <ContextMenu Visibility="Hidden"/>
         </TextBox.ContextMenu>
      </TextBox>

А также можно использовать:

           MyTextbox.ContextMenu.Visibility = Visibility.Hidden;
           MyTextbox.ContextMenu.Visibility = Visibility.Visble;

Попробуйте удалить атрибут x: Key из ресурса Style, оставив TargetType. Я знаю, что у вас должен быть этот x: Key для ресурса, но если он у вас есть вместе с вашим TargetType, ключ имеет преимущественную силу.

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

 <Style
    TargetType="{x:Type ToolTip}">
    <Setter
      Property="Template">
      <Setter.Value>
        <ControlTemplate
          TargetType="{x:Type ToolTip}">
          <Grid
            Width="{TemplateBinding Width}"
            Height="{TemplateBinding Height}">
            <Rectangle
              RadiusX="9"
              RadiusY="9"
              Stroke="LightGray"
              StrokeThickness="2">
              <Rectangle.Fill>
                <RadialGradientBrush>
                  <GradientStop />
                  <GradientStop
                    Color="FloralWhite"
                    Offset="0" />
                  <GradientStop
                    Color="Cornsilk"
                    Offset="2" />
                </RadialGradientBrush>
              </Rectangle.Fill>
            </Rectangle>
            <ContentPresenter
              Margin="6 4 6 4" />
          </Grid>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>

Неважно, если вы не предоставите ключ, он будет использовать TargetType ключ as точно так же, как и в моем примере :)

Взято из MSDN в стиле:

Установка TargetTypeсвойства для TextBlockтипа без установки x:Keyнеявно устанавливает x:Keyдля свойства значение {x:Type TextBlock}. Это также означает, что если вы>> дадите указанному выше Style x:Keyзначение, отличное от {x:Type TextBlock}, Style не будет автоматически применяться ко всем элементам TextBlock. Вместо этого вам нужно TextBlockявно применить стиль к элементам.

http://msdn.microsoft.com/en-us/library/system.windows.style.targettype.aspx

Чтобы стилизовать ContextMenu для всех текстовых полей, я бы сделал что-то вроде следующего:

Сначала в разделе ресурсов добавьте ContextMenu, которое вы планируете использовать в качестве стандартного ContextMenu в текстовом поле.
например

<ContextMenu x:Key="TextBoxContextMenu" Background="White">
  <MenuItem Command="ApplicationCommands.Copy" />
  <MenuItem Command="ApplicationCommands.Cut" />
  <MenuItem Command="ApplicationCommands.Paste" />
</ContextMenu>

Во-вторых, создайте стиль для ваших текстовых полей, который использует ресурс контекстного меню:

<Style TargetType="{x:Type TextBox}">
  <Setter Property="ContextMenu" Value="{StaticResource TextBoxContextMenu}" />
</Style>

Наконец, используйте текстовое поле как обычно:

<TextBox />

Если вместо этого вы хотите применить это контекстное меню только к некоторым из ваших текстовых полей, не создавайте стиль выше и добавьте следующее в разметку TextBox:

<TextBox ContextMenu="{StaticResource TextBoxContextMenu}" />

Надеюсь это поможет!