2013-07-11 53 views
1

我正在嘗試獲取ContextMenu的SelectedItem。ContextMenu的SelectedItem爲null

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> 

代碼隱藏

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); 
     } 
    } 
} 

你可以複製/粘貼代碼和程序應該工作。

該程序執行以下操作:

您可以選擇在列表框中的項目。如果您點擊「刪除項目」,該項目將被刪除並添加到ContextMenu中。如果您單擊ContextMenu-Item,則應將該項目再次添加到列表框並從ContextMenu中移除。你應該可以一遍又一遍......

因此,ContextMenu被綁定到一個集合。我得到的項目爲ic.CurrentItem。 問題是,當我刪除列表框中的項目並再次添加它時(通過單擊ContextMenu上的項目),ic.CurrentItem將爲空。

爲什麼?

編輯: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

魯迪,從我的知識,你不能分配前夕nt處理器綁定源中的單個對象。您只能使用WPF事件處理程序來處理綁定的對象,因此,您必須手動填充上下文菜單,以便您可以在此時添加事件處理程序。簡而言之,當您向WPF添加 ​​時,處理程序被分配到上下文菜單,但是當綁定添加了單個菜單項時,它不會將該處理程序添加到每個項目,從而使事件變得無用;-)下面是代碼,將解決這個問題:

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> 

代碼背後:

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'將'var ic'分配給ViewModel。 – Rudi