我用MainWindow和Model创建了一个简单的项目来显示问题。 我的目的是在某些ObservableCollection为空时隐藏MenuItem。我设法在Converter的帮助下为“Visibility”属性创建了一个绑定。 但问题是第一次打开ContextMenu时的状态是锁定的,甚至在更改绑定到“可见性”的“Items”对象之后,它也不再改变其状态。 这意味着如果我在任何按钮之前按下RMB,则只显示“BBB”MenuItem。但如果我之前按“显示AAA”按钮,“AAA”将在ContextMenu中显示。 我希望从ContextMenu外部控制“AAA”MenuItem的出现/消失。
MainWindow.xaml:
<Window x:Class="TestWpfContextMenu.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:testWpfContextMenu="clr-namespace:TestWpfContextMenu">
<Window.Resources>
<testWpfContextMenu:C2VConverter x:Key="Converter"/>
</Window.Resources>
<Window.ContextMenu>
<ContextMenu>
<MenuItem Header="AAA" Visibility="{Binding Items, Converter={StaticResource Converter}, Mode=OneWay}"/>
<Separator Visibility="{Binding Items, Converter={StaticResource Converter}, Mode=OneWay}"/>
<MenuItem Header="BBB"/>
</ContextMenu>
</Window.ContextMenu>
<Grid>
<Button Content="Show AAA" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
<Button Content="Hide AAA" HorizontalAlignment="Left" Margin="10,35,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click_1"/>
</Grid>
</Window>
使用代码隐藏:
using System;
using System.Collections;
using System.Globalization;
using System.Linq;
using System.Windows;
using System.Windows.Data;
namespace TestWpfContextMenu
{
public partial class MainWindow : Window
{
public MainWindow(Model model)
{
DataContext = model;
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
((Model) DataContext).Show();
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
((Model)DataContext).Hide();
}
}
public class C2VConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var elements = (IEnumerable )value;
if (elements == null)
return Visibility.Collapsed;
return elements.Cast<object>().Any() ? Visibility.Visible : Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
和DataContext aka Model是:
using System.Collections.ObjectModel;
namespace TestWpfContextMenu
{
public class Model
{
public Model()
{
Items = new ObservableCollection<object>();
}
public ObservableCollection<object> Items { get; set; }
public void Show()
{
Items.Add(new object());
}
public void Hide()
{
Items.Clear();
}
}
}
答案 0 :(得分:2)
正如我的评论中所述,您的绑定仅评估Items
属性本身。
您可以在模型中执行以下操作:
public class Model : INotifyPropertyChanged
{
public Model()
{
Items = new ObservableCollection<object>();
}
void Items_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
this.OnPropertyChanged("Items");
}
protected ObservableCollection<object> _Items;
public ObservableCollection<object> Items
{
get
{
return this._Items;
}
set
{
if (this._Items == value)
{
return;
}
if(this._Items != null)
{
this._Items.CollectionChanged -= Items_CollectionChanged;
}
this._Items = value;
this._Items.CollectionChanged += Items_CollectionChanged;
this.OnPropertyChanged();
}
}
public void Show()
{
Items.Add(new object());
}
public void Hide()
{
Items.Clear();
}
#region INPC
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string name = "")
{
PropertyChangedEventHandler tmp = this.PropertyChanged;
if (tmp != null)
{
tmp(this, new PropertyChangedEventArgs(name));
}
}
#endregion
}
当收集内容发生变化时,这将触发PropertyChanged
事件。也许其他人可以提出更优雅的解决方案。