2014-10-15 5 views
7

TextBox의 표준 ContextMenu를 비활성화해야합니다. 나는 새로운 WPF 프로젝트를 만든 다음 추가 한 :WPF ContextMenu = {x : Null}하지만 ContentControl 내에 여전히 메뉴가 표시됩니다.

<Window x:Class="WpfApplication3.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="350" Width="525"> 
    <Grid> 
     <ContentControl> 
      <ContentControl.ContentTemplate> 
       <DataTemplate> 
        <TextBox ContextMenu="{x:Null}" VerticalAlignment="Top" HorizontalAlignment="Left" Width="50"></TextBox> 
       </DataTemplate> 
      </ContentControl.ContentTemplate> 
     </ContentControl> 
    </Grid> 
</Window> 

을하지만 내가 무엇을 얻을 수 있습니다 :

enter image description here

다음 코드는 잘 작동 :

<Grid> 
    <TextBox ContextMenu="{x:Null}" VerticalAlignment="Top" HorizontalAlignment="Left" Width="50"></TextBox> 
</Grid> 

왜 이 일이 일어 났습니까?

업데이트.

Answer ContextMenu를 부모에게 보여주기 위해 TextBox에서 파생 된 클래스를 만들었습니다. 당신이 텍스트 상자에의 ContextMenu를 해제 됐는지하면서 다른 컨트롤에 있다면, 당신은 실제로 같은 래퍼의의 ContextMenu를 볼 수 있다는

public class TextBoxNoMenu: TextBox 
    { 
     public TextBoxNoMenu() 
     { 
      ContextMenu = null; 
     } 
    } 

답변

3

왜 이런 일이 : 더 좋은 방법은 가시성의 변경하는 것?

이것은 컨트롤의 동작이 흥미롭고 속성이 설정되는 위치에 따라 변경되는 경우입니다.

TextBox은 기본적으로 자체 컨텍스트 메뉴를 제공합니다. 시간 만 지정하면 로컬 값ContextMenu에서 null으로 명시 적으로 설정됩니다. 이는 간단한 예제에서 TextBox이 직접적으로 Grid에있는 경우 발생합니다.

그러나 템플릿을 템플릿에 설정하면 실제로는 로컬 값을 설정하지 않습니다. 당신은 "부모 템플릿"값을 설정하고 있습니다. DependencyPropertyHelper.GetValueSource()으로 값을 검사하면 Local 대신 기본 값 소스가 ParentTemplate임을 알 수 있습니다. 따라서 메뉴는 여전히 무시됩니다.

다양한 종류의 종속성 속성 값 소스에 대한 자세한 내용은 Dependency Property Value Precedence을 참조하십시오.

@ OmegaMan의 '숨겨진'컨텍스트 메뉴를 지정하면 꽤 잘 작동하는 것 같습니다.

+0

첫 번째 목표는 부모의 ContextMenu를 여는 것이 었습니다. 그래서 붕괴는 실제 문제를 해결하지 못합니다. 그러나, 당신이 대답을 보았을 때 TextBox에서 파생 된 클래스 TextBoxNoMenu를 만들고 해당 컨텍스트 메뉴를 무효화했습니다. –

1

참고. 더 구체적으로 이런 종류의 동작을 보려면 Snooping을 시도하십시오.

WPF에서 기본 컨트롤 템플릿이 많은 경우 자체 자식 개체를 추가하여 이러한 문제가 발생할 수 있습니다. default template for TextBox을 보면 Border을 사용하고 <ScrollViewer Margin="0" x:Name="PART_ContentHost" />을 사용하면 TextBox 인 경우 하위 개체의 ContextMenu가 표시됩니다.

+0

위의 코드는 솔루션에있는 모든 것입니다. 따라서 유일한 래퍼는 ContentControl입니다. 또한 ContentControl의 ContextMenu를 null로 설정하면 동일한 잘못된 동작이 발생합니다. –

+0

TextBox에서 일부 자식을 추가하지 않는 것으로 가정합니다. 그에 따라 내 대답 업데이트. – David

1

이것은 X : Null이 기본 상황에 맞는 메뉴를 '끄지'않은 경우 실행되는 문제인 것처럼 보입니다.

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

나는 비슷한 문제가 있었지만 프로그래밍 방식으로 컨트롤을 생성하고 부모 컨트롤은 dockpanel입니다. 허용 된 대답에 따라 코드 뒤에 null 값을 설정하기로 결정했습니다.

 <Grid> 
      <DockPanel> 
       <TextBox Name="txtBox" VerticalAlignment="Top" HorizontalAlignment="Left" Width="50"></TextBox> 
      </DockPanel> 
     </Grid> 

다음

  private void Window_Loaded(object sender, RoutedEventArgs e) 
      { 
       txtBox.ContextMenu = null; 
      } 

편집 : 나는 완전히 또는 직접이 문제가 해결되지는 않습니다,이는 우연한 대답의 종류 느꼈다. 나는 약간의 파고를했고 만약 여러분이 This Question에 대한 답에서 발견 된 메소드를 구현한다면 코드 숨김에서 텍스트 박스를 찾을 수 있습니다. 이

 <Grid> 
      <ContentControl> 
       <ContentControl.ContentTemplate> 
       <DataTemplate> 
        <TextBox Name="txtBox" VerticalAlignment="Top" HorizontalAlignment="Left" Width="50"></TextBox> 
       </DataTemplate> 
       </ContentControl.ContentTemplate> 
      </ContentControl> 
     </Grid> 

이있는 경우

그래서, 그럼 당신은 (txtBox이 경우) 이름으로 텍스트 상자를 찾을 수 및 I

   TextBox myTextBox = FindChild<TextBox>(Application.Current.MainWindow, "txtBox"); 

       myTextBox.ContextMenu = null; 

을 개인적으로 null로 상황에 맞는 메뉴를 설정해야합니다 상속을 사용하여 새로운 클래스를 만드는 것이이 방법을 선호하지만, 무엇이든지 당신을 위해 작동합니다. 이것은 여전히 ​​"왜 이런 일이 일어 났습니까?"라고 대답하지 않습니다. 그러나 나는 받아 들여지는 대답이 그것의 좋은 일을한다고 생각한다.