繁体   English   中英

MenuItem.IsEnabled绑定到列表框中是否选择了某些内容,但不会更新

[英]MenuItem.IsEnabled is bound to whether there is something selected in Listbox or not, but it doesn't update

我有一个MenuItem,只有在ListBox中选择了某些东西时才应启用它。 我编写了一个从对象到布尔的转换器,如果该对象== null,则返回false,否则返回true。 我用转换器将其绑定到ListBox.SelectedItem,但是它不起作用。 在转换器中放置一个断点表明它永远不会运行。 无论如何,菜单项始终显示为启用状态。

这是ListBox和MenuItem的xaml代码

<ListBox Name="TestsListBox" 
         HorizontalAlignment="Left" Height="93" VerticalAlignment="Top" Width="128"
         Margin="0,5,-1.723,0" ItemsSource="{Binding Path=Tests, Mode=OneWay}">
    <ListBox.ContextMenu>
        <ContextMenu>
            <MenuItem Header="Remove" Click="removeTest"
                      IsEnabled="{Binding ElementName=TestsListBox, Mode=OneWay,
                                          Path=SelectedItem, Converter={StaticResource ObjectToBool}}"/>
        </ContextMenu>
    </ListBox.ContextMenu>
</ListBox>

在这里,我展示了如何将转换器声明为窗口的资源

<Window x:Class="WpfApplication.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:System="clr-namespace:System;assembly=mscorlib"
        xmlns:ClassesLib="clr-namespace:Laba1;assembly=ClassesLib"
        xmlns:local="clr-namespace:WpfApplication"
        Title="MainWindow" Height="450" Width="525">
    <Window.Resources>
        <local:ObjectToBoolConverter x:Key="ObjectToBool"/>
    </Window.Resources>

这是转换器类

namespace WpfApplication
{
    class ObjectToBoolConverter: IValueConverter
    {
        // Converts value to boolean. If value is null, returns false.
        // Otherwise returns true
        public object Convert(object value, Type targetType,
            object parameter, System.Globalization.CultureInfo culture)
        {
            if (null == value)
            {
                return false;
            }
            return true;
        }
        public object ConvertBack(object value, Type targetType,
            object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotSupportedException("This is oneway converter, so ConvertBack is not supported");
        }
    }
}

RelativeSource和弹出窗口

从这里您应该能够发现ElementName绑定不起作用的原因是因为ContextMenu不像其他控件那样属于可视化树的一部分,因此不能参与此类绑定方案。 AFAIK,PopUps具有一个PlacementTarget属性,您可以将其绑定并确定如何使用。

这就是我解决的方法:

视图:

<Window x:Class="WpfApplication2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:local="clr-namespace:WpfApplication2"
          Title="MainWindow" Height="350" Width="525">
<Window.Resources>
    <local:ObjectToBoolConverter x:Key="ObjectToBool"/>
        <ContextMenu x:Key="contextMenu" DataContext="{Binding PlacementTarget.SelectedItem, RelativeSource={RelativeSource Self}}">
            <MenuItem Header="Remove" Click="removeTest"
                      IsEnabled="{Binding Path=., Converter={StaticResource ObjectToBool}}"/>

        </ContextMenu>
    </Window.Resources>

    <Grid>
        <ListBox Name="TestsListBox" 
         HorizontalAlignment="Left" Height="93" VerticalAlignment="Top" Width="128" 
         Margin="0,5,-1.723,0" ContextMenu="{StaticResource ResourceKey=contextMenu}">
        </ListBox>
    </Grid>
</Window>

后面的代码

using System.Collections.Generic;
using System.Windows;
using System.Windows.Documents;

namespace WpfApplication2
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = this;
            List<string> teste = new List<string>();
            teste.Add("test1");
            teste.Add("test3");
            teste.Add("test2");

            TestsListBox.ItemsSource = teste;

        }

        private void removeTest(object sender, RoutedEventArgs e)
        {

        }
    }
}

转换器保持不变。

问候,

看起来Binding的ElementName属性没有执行我认为的操作。 XAML只会忽略它,而且对Binding的不正确参数也不做任何事情:它应该引发错误。 我将DataContext添加到我的ContextMenu中,删除了ElementName,并且现在可以正常工作。 这就是我更改代码的方式:

<ContextMenu DataContext="{Binding PlacementTarget, RelativeSource={RelativeSource Self}}" >
    <MenuItem Header="Add" Click="addTest"/>
    <MenuItem Header="Remove" Click="removeTest"
              IsEnabled="{Binding Mode=OneWay,
                                  Path=SelectedItem, Converter={StaticResource ObjectToBool}}"/>
</ContextMenu>

即使我认为可以使用ElementName代替DataContext,Dtex对重复项的评论也帮助了我。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM