我正在尝试设置一些行为来控制MVVM应用程序中的窗口。
我的想法是行为可以在XAML中进行装饰设置并存在于他们自己的类中,允许在某些情况下在许多不同的视图中重用它们。
我还有一个绑定到RelayCommand的菜单项。这两种方法都可以自行完成,但是当我尝试将这两种方法结合起来时,这些方法无法正常工作:
MainView.xaml
<Window x:Class="CaseManager.Views.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:VM="clr-namespace:CaseManager.ViewModels;assembly=CaseManager.ViewModels"
xmlns:local="clr-namespace:CaseManager.Views"
local:ExitBehavior.ExitWhen="{Binding ExitFlag}"
Title="Main Window" Height="350" Width="525">
<Window.DataContext>
<VM:MainViewModel />
</Window.DataContext>
<Grid>
<Menu Height="20" VerticalAlignment="Top">
<MenuItem Header="_File">
<MenuItem Header="_Exit" Command="{Binding ExitCommand}" />
</MenuItem>
</Menu>
</Grid>
</Window>
MainViewModel.cs
namespace CaseManager.ViewModels
{
using System;
using System.Collections.Generic;
using Commands;
public class MainViewModel : ViewModelBase
{
# region RelayCommands
private RelayCommand _exitCommand;
public RelayCommand ExitCommand
{
get { return _exitCommand; }
private set { _exitCommand = value; }
}
#endregion
private bool _exitFlag;
public bool ExitFlag {
get { return _exitFlag; }
private set { _exitFlag = value; }
}
public MainViewModel()
{
ExitCommand = new RelayCommand(ExitCommand_Execute);
ExitFlag = false;
}
private void ExitCommand_Execute(object obj)
{
System.Console.WriteLine("Command executed");
ExitFlag = true;
}
}
}
ExitCommand.cs
namespace CaseManager.Views
{
using System;
using System.Windows;
public static class ExitBehavior
{
public static bool GetExitWhen(DependencyObject obj)
{
return (bool)obj.GetValue(ExitWhenProperty);
}
public static void SetExitWhen(DependencyObject obj, bool value)
{
obj.SetValue(ExitWhenProperty, value);
}
public static readonly DependencyProperty ExitWhenProperty =
DependencyProperty.RegisterAttached(
"ExitWhen", typeof(bool), typeof(ExitBehavior),
new UIPropertyMetadata(OnExitWhenChanged));
static void OnExitWhenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
System.Console.WriteLine("Behavior executed");
Environment.Exit(0);
}
}
}
当我在菜单中选择退出时,按原样运行上面的代码将在控制台中输出'Command executed'。所以我知道relay命令工作正常。但是行为不是。
如果我将MainViewModel
的构造函数更改为将ExitFlag
设置为true,程序将启动,将“执行行为”打印到控制台,然后退出。
ExitBehavior和RelayCommand都可以自行工作,但是当我尝试通过在relay命令中设置ExitFlag来触发ExitBehavior时,它们不能一起使用。我在这里错过了什么吗?
为简洁起见,RelayCommand.cs
:
namespace CaseManager.Commands
{
using System;
using System.Windows.Input;
public class RelayCommand : ICommand
{
#region Fields
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
#endregion
#region Constructors
public RelayCommand(Action<object> execute)
: this(execute, null)
{
}
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
#endregion
#region ICommand Members
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
_execute(parameter);
}
#endregion
}
}
答案 0 :(得分:3)
您必须通知绑定引擎,您的属性ExitFlag
已更改。假设ViewModelBase
以某种方式实现INotifyPropertyChanged
:
public bool ExitFlag
{
get { return _exitFlag; }
private set
{
_exitFlag = value;
OnPropertyChanged("ExitFlag");
}
}
其中OnPropertyChanged
是一种方法,可以引发INPC.PropertyChanged
事件。
答案 1 :(得分:0)
正如我从你的代码中所理解的那样,在这里:
local:CloseBehavior.CloseWhen="{Binding CloseFlag}"
必须有一个属性ExitFlag
。
其次,此属性应从INotifyPropertyChanged
接口调用OnPropertyChanged
方法来更新属性,而在XAML中应该如下:
local:CloseBehavior.CloseWhen="{Binding Path=ExitFlag, Mode=TwoWay}"