ContextMenu的SelectedItem为null

时间:2013-07-11 14:04:18

标签: c# binding contextmenu selecteditem

我正在尝试获取ContextMenu的SelectedItem。

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

您可以复制/粘贴代码,程序应该可以正常工作。

该计划正在执行以下操作:

您可以在ListBox中选择一个项目。如果单击“删除项目”,该项将被删除并添加到ContextMenu。如果单击ContextMenu-Item,则应将该项再次添加到ListBox并从ContextMenu中删除。你应该能够一遍又一遍地做到这一点......

因此ContextMenu被绑定到一个集合。我得到了ic.CurrentItem的项目。 问题是,当我删除ListBox中的项目并再次添加它(通过单击ContextMenu上的项目)时,ic.CurrentItem将为null。

为什么?

编辑:Cyphryx的解决方案正在运行,但现在我正在尝试使用MVVM / Binding来做同样的事情:

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 个答案:

答案 0 :(得分:1)

Rudi,据我所知,你不能将事件处理程序分配给绑定源中的单个对象。您只能将WPF事件处理程序用于它所绑定的对象,因此,您必须手动填充上下文菜单,允许您在此时添加事件处理程序。简而言之,当你添加 PreviewMouseDown="ContextMenu_PreviewMouseDown"给你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