我在课程中有一个ObservableCollection<T>
,我希望将IsEnabled
元素的MenuItem
属性与ObservableCollection<T>
Items.Any()
XAML =&gt;
<MenuItem x:Name="MyMenu"
IsEnabled="{Binding ????}"
Header="MENU">
</MenuItem>
C#=&gt;
public class MyClass
{
public static MyClass Current = new MyClass();
public ObservableCollection<Object> Items { get; } = new ObservableCollection<Object>();
}
答案 0 :(得分:3)
执行此操作的惯用方法是将菜单项绑定到命令,并让命令的CanExecute
处理程序检查您的Items
集合是否为空。如果MenuItem
返回CanExecute
,则false
会自动停用。
public class MyViewModel : INotifyPropertyChanged
{
public ObservableCollection<Object> Items { get; }
public DelegateCommand MenuItemCommand { get; }
public MyViewModel()
{
Items = new ObservableCollection<object>();
MenuItemCommand = new DelegateCommand(
() => { /* Do Something */ },
() => Items.Count > 0);
Items.CollectionChanged += (s, e) => MenuItemCommand.RaiseCanExecuteChanged();
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
根据MVVM模式,您应该将屏幕的DataContext
(例如,您的UserControl
,Page
或Window
)设置为视图的实例模型。
要将菜单项连接到命令,请按如下所示修改Xaml:
<MenuItem Command="{Binding MenuItemCommand}"
Header="MENU" />
有无数DelegateCommand
实现的例子(有时称为RelayCommand
),但为了完整性我会在这里包含一个:
public class DelegateCommand : ICommand
{
private readonly Action _execute;
private readonly Func<bool> _canExecute;
public DelegateCommand(Action execute, Func<bool> canExecute = null)
{
_execute = execute ?? throw new ArgumentNullException(nameof(execute));
_canExecute = canExecute;
}
public virtual bool CanExecute() => _canExecute?.Invoke() ?? true;
public virtual void Execute() => _execute();
public void RaiseCanExecuteChanged()
{
OnCanExecuteChanged();
}
public event EventHandler CanExecuteChanged;
protected virtual void OnCanExecuteChanged()
{
this.CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
bool ICommand.CanExecute(object parameter)
{
return this.CanExecute();
}
void ICommand.Execute(object parameter)
{
this.Execute();
}
}
IsEnabled
如果您坚持不使用命令,则可以执行以下操作:
public class MyViewModel : INotifyPropertyChanged
{
public ObservableCollection<Object> Items { get; }
public bool HasItems => Items.Count > 0;
public MyViewModel()
{
Items = new ObservableCollection<object>();
Items.CollectionChanged += (s, e) => OnPropertyChanged(nameof(HasItems));
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
按照以下步骤更新您的Xaml:
<MenuItem IsEnabled="{Binding HasItems}"
Header="MENU" />
答案 1 :(得分:1)
您可以使用Style
并直接绑定到Count
属性:
<MenuItem x:Name="MyMenu" Header="MENU">
<MenuItem.Style>
<Style TargetType="MenuItem">
<Style.Triggers>
<DataTrigger Binding="{Binding Items.Count}" Value="0">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</MenuItem.Style>
</MenuItem>
ObservableCollection<T>
每次Count
属性更改时都会引发更改通知。
答案 2 :(得分:1)
您可以绑定到SELECT * FROM "schema1"."items" UNION SELECT * FROM "schema2"."items";
属性并创建一个值转换器,将0转换为false,将非零转换为true:
ObservableCollection<T>.Count
然后将您的转换器添加到资源并使用绑定:
public class HasItemsConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return (value as int?) > 0;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}