상황에 맞는 메뉴의 메뉴 항목에서 요소 이름 바인딩
ElementName을(를) 사용한 바인딩이 다음에 대해 올바르게 해결되지 않음을 다른 사용자가 눈치챘습니까?MenuItem
안에 포함된 개체ContextMenu
물건?이 샘플을 확인하십시오.
<Window x:Class="EmptyWPF.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300"
x:Name="window">
<Grid x:Name="grid" Background="Wheat">
<Grid.ContextMenu>
<ContextMenu x:Name="menu">
<MenuItem x:Name="menuItem" Header="Window" Tag="{Binding ElementName=window}" Click="MenuItem_Click"/>
<MenuItem Header="Grid" Tag="{Binding ElementName=grid}" Click="MenuItem_Click"/>
<MenuItem Header="Menu" Tag="{Binding ElementName=menu}" Click="MenuItem_Click"/>
<MenuItem Header="Menu Item" Tag="{Binding ElementName=menuItem}" Click="MenuItem_Click"/>
</ContextMenu>
</Grid.ContextMenu>
<Button Content="Menu"
HorizontalAlignment="Center" VerticalAlignment="Center"
Click="MenuItem_Click" Tag="{Binding ElementName=menu}"/>
<Menu HorizontalAlignment="Center" VerticalAlignment="Bottom">
<MenuItem x:Name="anotherMenuItem" Header="Window" Tag="{Binding ElementName=window}" Click="MenuItem_Click"/>
<MenuItem Header="Grid" Tag="{Binding ElementName=grid}" Click="MenuItem_Click"/>
<MenuItem Header="Menu" Tag="{Binding ElementName=menu}" Click="MenuItem_Click"/>
<MenuItem Header="Menu Item" Tag="{Binding ElementName=anotherMenuItem}" Click="MenuItem_Click"/>
</Menu>
</Grid>
</Window>
컨텍스트 메뉴에 포함된 바인딩을 제외한 모든 바인딩이 잘 작동합니다.런타임 중에 오류가 출력 창에 인쇄됩니다.
주변에 대해 아는 사람?이게 무슨 일입니까?
저는 훨씬 더 간단한 해결책을 찾았습니다.
UserControl의 코드 뒤에 있는 내용:
NameScope.SetNameScope(contextMenu, NameScope.GetNameScope(this));
다른 사용자가 말했듯이 'ContextMenu'는 비주얼 트리에 포함되어 있지 않으며 'ElementName' 바인딩이 작동하지 않습니다.상황에 맞는 메뉴의 'NameScope'를 수락된 답변에서 제안한 대로 설정하면 상황에 맞는 메뉴가 'DataTemplate'에 정의되지 않은 경우에만 작동합니다.이 문제는 'ElementName' 바인딩과 유사하지만 바인딩을 다르게 확인하는 {x:Reference} Markup-Extension을 사용하여 해결했습니다. 이 바인딩은 시각적 트리를 우회합니다.저는 이것이 '배치 대상'을 사용하는 것보다 훨씬 더 읽기 쉽다고 생각합니다.다음은 예입니다.
<Image Source="{Binding Image}">
<Image.ContextMenu>
<ContextMenu>
<MenuItem Header="Delete"
Command="{Binding Source={x:Reference Name=Root}, Path=DataContext.RemoveImage}"
CommandParameter="{Binding}" />
</ContextMenu>
</Image.ContextMenu>
</Image>
MSDN 문서에 따라
x:Reference는 XAML 2009에 정의된 구성입니다.WPF에서는 XAML 2009 기능을 사용할 수 있지만 WPF 마크업 컴파일되지 않은 XAML에만 사용할 수 있습니다.마크업 컴파일된 XAML 및 XAML의 BAML 형식은 현재 XAML 2009 언어 키워드 및 기능을 지원하지 않습니다.
그게 무슨 뜻이든 간에...하지만 저한테는 효과가 있어요.
다음은 xaml 전용 해결 방법입니다.(또한 이는 데이터 컨텍스트 내에 있는 것(예: MVVMing 중)을 원하는 것으로 가정합니다.
옵션 1. 컨텍스트 메뉴의 상위 요소가 데이터 템플릿에 없는 경우:
Command="{Binding PlacementTarget.DataContext.MyCommand,
RelativeSource={RelativeSource AncestorType=ContextMenu}}"
이것은 OP의 질문에 효과가 있을 것입니다.데이터 템플릿 내부에 있는 경우에는 작동하지 않습니다.이러한 경우 DataContext는 컬렉션에 포함된 여러 개 중 하나이며 바인딩하려는 IC 명령은 동일한 ViewModel(예: 창의 DataContext) 내 컬렉션의 형제 속성입니다.
이러한 경우 태그를 사용하여 컬렉션과 IC 명령이 모두 포함된 상위 DataContext를 일시적으로 유지할 수 있습니다.
class ViewModel
{
public ObservableCollection<Derp> Derps { get;set;}
public ICommand DeleteDerp {get; set;}
}
그리고 시험에서.
<!-- ItemsSource binds to Derps in the DataContext -->
<StackPanel
Tag="{Binding DataContext, ElementName=root}">
<StackPanel.ContextMenu>
<ContextMenu>
<MenuItem
Header="Derp"
Command="{Binding PlacementTarget.Tag.DeleteDerp,
RelativeSource={RelativeSource
AncestorType=ContextMenu}}"
CommandParameter="{Binding PlacementTarget.DataContext,
RelativeSource={RelativeSource AncestorType=ContextMenu}}">
</MenuItem>
상황에 맞는 메뉴는 바인딩하기 어렵습니다.컨트롤의 시각적 트리 외부에 존재하므로 요소 이름을 찾을 수 없습니다.
상황에 맞는 메뉴의 데이터 컨텍스트를 배치 대상으로 설정해 보십시오.RelativeSource를 사용해야 합니다.
<ContextMenu
DataContext="{Binding PlacementTarget, RelativeSource={RelativeSource Self}}"> ...
약간의 실험을 한 후, 저는 한 가지 해결책을 발견했습니다.
최상위 수준으로 만들기Window
/UserControl
INameScope
트세를 합니다.NameScope
ContextMenu
최고 수준의 제어 장치로.
public class Window1 : Window, INameScope
{
public Window1()
{
InitializeComponent();
NameScope.SetNameScope(contextMenu, this);
}
// Event handlers and etc...
// Implement INameScope similar to this:
#region INameScope Members
Dictionary<string, object> items = new Dictionary<string, object>();
object INameScope.FindName(string name)
{
return items[name];
}
void INameScope.RegisterName(string name, object scopedElement)
{
items.Add(name, scopedElement);
}
void INameScope.UnregisterName(string name)
{
items.Remove(name);
}
#endregion
}
이를 통해 컨텍스트 메뉴가 내부에서 이름이 지정된 항목을 찾을 수 있습니다.Window
다른 방법은?
이미 처리한 마우스 클릭에 대해 이벤트 핸들러 내부의 코드 한 줄을 피하기 위해 마술 묘기에 의존하는 이유가 무엇인지 잘 모르겠습니다.
private void MenuItem_Click(object sender, System.Windows.RoutedEventArgs e)
{
// this would be your tag - whatever control can be put as string intot he tag
UIElement elm = Window.GetWindow(sender as MenuItem).FindName("whatever control") as UIElement;
}
언급URL : https://stackoverflow.com/questions/1013558/elementname-binding-from-menuitem-in-contextmenu
'programing' 카테고리의 다른 글
특정 화이트리스트를 제외한 모든 HTML 태그를 필터링하려면 어떻게 해야 합니까? (0) | 2023.05.15 |
---|---|
Xcode에서 기호 파일 처리 (0) | 2023.05.10 |
Xib 파일에서 사용자 지정 UITableViewCells를 로드하는 방법은 무엇입니까? (0) | 2023.05.10 |
Node.js에서 사용되지 않는 패키지를 제거하거나 제거하는 npm 명령 (0) | 2023.05.10 |
jQuery 선택기의 와일드카드 (0) | 2023.05.10 |