[英]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");
}
}
}
从这里您应该能够发现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.