2013-07-11 5 views
1

ContextMenu의 SelectedItem을 가져 오려고합니다. 당신은/복사 코드를 붙여 넣 및 프로그램이 작동해야 할 수ContextMenu의 SelectedItem이 null입니다.

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     OCContext = new ObservableCollection<string>(); 
     MyList = new ObservableCollection<string>(); 
     MyList.Add("Item 1"); 
     MyList.Add("Item 2"); 
     InitializeComponent(); 
    } 

    public ObservableCollection<string> MyList { get; set; } 
    public ObservableCollection<string> OCContext { get; set; } 
    public string MySelectedItem { get; set; } 

    private void ContextMenu_PreviewMouseDown(object sender, MouseButtonEventArgs e) 
    { 
     MenuBase s = sender as MenuBase; 
     ItemCollection ic = s.Items; 
     string MyItem = ""; 
     MyItem = (string)ic.CurrentItem; 
     MyList.Add(MyItem); 
     OCContext.Remove(MyItem); 
    } 

    private void Button_Click(object sender, RoutedEventArgs e) 
    { 
     if (MySelectedItem != null) 
     { 
      OCContext.Add(MySelectedItem); 
      MyList.Remove(MySelectedItem); 
     } 
    } 
} 

뒤에

XAML

<Window x:Class="WpfApplication1.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" 
     DataContext="{Binding RelativeSource={RelativeSource Self}}"> 
    <Grid> 
     <StackPanel> 
     <ListBox x:Name="MyListBox" ItemsSource="{Binding MyList}" SelectedItem="{Binding MySelectedItem}"> 
      <ListBox.ContextMenu> 
       <ContextMenu ItemsSource="{Binding OCContext}" PreviewMouseDown="ContextMenu_PreviewMouseDown"/> 
      </ListBox.ContextMenu> 
     </ListBox> 
     <Button Content="Delete Item" Click="Button_Click"/> 
     </StackPanel> 
    </Grid> 
</Window> 

코드입니다.

프로그램

는 다음을 수행한다 :

당신은 목록 상자에서 항목을 선택할 수 있습니다. "항목 삭제"를 클릭하면 해당 항목이 삭제되고 ContextMenu에 추가됩니다. ContextMenu-Item을 클릭하면 해당 항목을 ListBox에 다시 추가하고 ContextMenu에서 제거해야합니다. 이 작업을 반복해서 할 수 있어야합니다 ...

그래서 ContextMenu가 컬렉션에 바인딩됩니다. 나는 ic.CurrentItem으로 아이템을 얻는다. 문제는 ListBox에서 항목을 삭제하고 ContextMenu의 항목을 클릭하여 다시 추가 할 때 ic.CurrentItem이 null이된다는 것입니다.

왜?

편집 : Cyphryx의 솔루션이 작동하지만, 지금은 바인딩/MVVM을 사용하여 동일한 작업을 수행하기 위해 노력하고있어 :

XAML :

<ContextMenu x:Name="MyContext" ContextMenu="{Binding MyContextMenu}" ItemsSource="{Binding OCContext}"/> 

뷰 모델 :

private ObservableCollection<string> _occontext; 
    public ObservableCollection<string> OCContext 
    { 
     get 
     { 
      if (_occontext == null) 
       _occontext = new ObservableCollection<string>(); 
      MyContextMenu.Items.Clear(); 
      foreach (var str in _occontext) 
      { 
       var item = new System.Windows.Controls.MenuItem(); 
       item.Header = str; 
       item.Click += Content_MouseLeftButtonUp; 
       MyContextMenu.Items.Add(item); 
      } 

      return _occontext; 
     } 
     set 
     { 
      _occontext = value; 
      RaisePropertyChanged(() => OCContext); 
     } 
    } 

    private void Content_MouseLeftButtonUp(object sender, RoutedEventArgs e) 
    { 
     var s = sender as System.Windows.Controls.MenuItem; 
     if (s == null) return; 
     string ic = s.Header.ToString(); 
    } 

    private System.Windows.Controls.ContextMenu _mycontextmenu; 
    public System.Windows.Controls.ContextMenu MyContextMenu 
    { 
     get 
     { 
      if (_mycontextmenu == null) 
       _mycontextmenu = new System.Windows.Controls.ContextMenu(); 
      return _mycontextmenu; 
     } 
     set 
     { 
      _mycontextmenu = value; 
      RaisePropertyChanged(() => MyContextMenu); 
     } 
    } 

Content_MouseLeftButtonUp가 호출되지 않고 있습니까?

답변

1

루디, 내 지식으로는 이브를 할당 할 수 없습니다. 바인딩 된 소스의 개별 객체에 대한 처리기를 제공합니다. 묶여있는 개체에 대해서만 WPF 이벤트 처리기를 사용할 수 있으므로 상황에 맞는 메뉴를 수동으로 채워야하므로 그 시간에 이벤트 처리기를 추가 할 수 있습니다. 즉, PreviewMouseDown="ContextMenu_PreviewMouseDown"을 WPF에 추가하면 처리기가 상황에 맞는 메뉴에 할당되지만 바인딩이 개별 메뉴 항목을 추가하면 각 항목에 해당 처리기가 추가되지 않으므로 손쉽게 이벤트를 남길 수 있습니다. 이 문제를 해결하는 코드 :

<Window x:Class="WpfApplication1.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" 
     DataContext="{Binding RelativeSource={RelativeSource Self}}"> 
    <Grid> 
     <StackPanel> 
      <ListBox x:Name="MyListBox" ItemsSource="{Binding MyList}" SelectedItem="{Binding MySelectedItem}" Height="Auto" MinHeight="20"> 
       <ListBox.ContextMenu> 
        <ContextMenu Name="ContextMenu" Opened="ContextMenu_Opened" /> 
       </ListBox.ContextMenu> 
      </ListBox> 
      <Button Content="Delete Item" Click="Button_Click"/> 
     </StackPanel> 
    </Grid> 
</Window> 

코드 뒤에

WPF :

public MainWindow() 
{ 
    OCContext = new ObservableCollection<string>(); 
    MyList = new ObservableCollection<string>(); 
    MyList.Add("Item 1"); 
    MyList.Add("Item 2"); 
    InitializeComponent(); 

} 
public ObservableCollection<string> MyList { get; set; } 
public ObservableCollection<string> OCContext { get; set; } 
public string MySelectedItem { get; set; } 

private void ContextMenu_Opened(object sender, EventArgs e) 
{ 
    ContextMenu.Items.Clear(); 
    foreach (var str in OCContext) 
    { 
     var item = new MenuItem(); 
     item.Header = str; 
     item.Click += Content_MouseLeftButtonUp; 
     ContextMenu.Items.Add(item); 
    } 
} 

private void Content_MouseLeftButtonUp(object sender, EventArgs e) 
{ 
    var s = sender as MenuItem; 
    if (s == null) return; 
    var ic = s.Header.ToString(); 

    MyList.Add(ic); 
    OCContext.Remove(ic); 
} 

private void Button_Click(object sender, RoutedEventArgs e) 
{ 
    if (MySelectedItem != null) 
    { 
     OCContext.Add(MySelectedItem); 
     MyList.Remove(MySelectedItem); 
    } 
} 

난이 도움이되기를 바랍니다.

Cyphryx

+0

예, 덕분에 많은 도움이되었습니다. :). ContextMenu_PreviewMouseDown' 이외의 다른 이벤트를 찾을 수 없습니다 (MouseLeftButton을 보지 못했습니다 ...). 감사! 그리고 그것이 왜 효과가 없었는지 명확히하는 것에 대해서도 감사드립니다. – Rudi

+0

바인딩을 사용할 수 있습니까? MVVM을 사용하여 이것을 실제로 ViewModel에 넣고 싶습니다. 'ViewModelLocator.Main.MyValue = ic'을 사용하여 ViewModel에'var ic '을 할당하고 있습니다. – Rudi