C# MVVM混合行为和RelayCommand未按预期工作
我正在尝试设置一些行为来控制MVVM应用程序中的窗口 我的想法是,行为可以在XAML中装饰性地设置,并存在于它们自己的类中,允许在某些情况下在许多不同的视图中重用它们 我还有一个绑定到RelayCommand的菜单项。这两种方法各自都能很好地发挥作用,但当我尝试将这两种方法结合在一起时,却没有达到预期效果:C# MVVM混合行为和RelayCommand未按预期工作,c#,wpf,xaml,mvvm,C#,Wpf,Xaml,Mvvm,我正在尝试设置一些行为来控制MVVM应用程序中的窗口 我的想法是,行为可以在XAML中装饰性地设置,并存在于它们自己的类中,允许在某些情况下在许多不同的视图中重用它们 我还有一个绑定到RelayCommand的菜单项。这两种方法各自都能很好地发挥作用,但当我尝试将这两种方法结合在一起时,却没有达到预期效果: MainView.xaml <Window x:Class="CaseManager.Views.MainView" xmlns="http://schemas.mic
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>
ExitCommand.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;
}
}
}
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);
}
}
}
当我在菜单中选择exit时,按原样运行上述代码将在控制台中输出“Command executed”。所以我知道中继命令工作正常。然而,这种行为并非如此
如果我将我的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
}
}
namespace CaseManager.Commands
{
使用制度;
使用System.Windows.Input;
公共类中继命令:ICommand
{
#区域字段
只读操作_执行;
只读谓词_canExecute;
#端区
#区域构造函数
公共中继命令(操作执行)
:此(执行,空)
{
}
公共RelayCommand(操作执行,谓词canExecute)
{
if(execute==null)
抛出新的ArgumentNullException(“执行”);
_执行=执行;
_canExecute=canExecute;
}
#端区
#区域ICommand成员
公共布尔CanExecute(对象参数)
{
返回_canExecute==null?true:_canExecute(参数);
}
公共事件事件处理程序CanExecuteChanged
{
添加{CommandManager.RequerySuggested+=value;}
删除{CommandManager.RequerySuggested-=value;}
}
public void Execute(对象参数)
{
_执行(参数);
}
#端区
}
}
您必须通知绑定引擎,您的属性ExitFlag
已更改。假设ViewModelBase
以某种方式实现:
其中,
OnPropertyChanged
是一个方法,它会引发INPC.PropertyChanged
事件。您必须通知绑定引擎,您的属性ExitFlag
已更改。假设ViewModelBase
以某种方式实现:
其中,
OnPropertyChanged
是一个方法,它会引发INPC.PropertyChanged
事件。您必须通知绑定引擎,您的属性ExitFlag
已更改。假设ViewModelBase
以某种方式实现:
其中,
OnPropertyChanged
是一个方法,它会引发INPC.PropertyChanged
事件。您必须通知绑定引擎,您的属性ExitFlag
已更改。假设ViewModelBase
以某种方式实现:
其中,
OnPropertyChanged
是一个方法,它引发INPC.PropertyChanged
事件。首先,正如我从您的代码中理解的,这里:
local:CloseBehavior.CloseWhen="{Binding CloseFlag}"
必须有一个属性ExitFlag
其次,这个属性应该从接口调用OnPropertyChanged
方法来更新属性,在XAML中应该是:
local:CloseBehavior.CloseWhen="{Binding Path=ExitFlag, Mode=TwoWay}"
首先,正如我从您的代码中理解的,这里:
local:CloseBehavior.CloseWhen="{Binding CloseFlag}"
必须有一个属性ExitFlag
其次,这个属性应该从接口调用OnPropertyChanged
方法来更新属性,在XAML中应该是:
local:CloseBehavior.CloseWhen="{Binding Path=ExitFlag, Mode=TwoWay}"
首先,正如我从您的代码中理解的,这里:
local:CloseBehavior.CloseWhen="{Binding CloseFlag}"
必须有一个属性ExitFlag
其次,这个属性应该从接口调用OnPropertyChanged
方法来更新属性,在XAML中应该是:
local:CloseBehavior.CloseWhen="{Binding Path=ExitFlag, Mode=TwoWay}"
首先,正如我从您的代码中理解的,这里:
local:CloseBehavior.CloseWhen="{Binding CloseFlag}"
必须有一个属性ExitFlag
其次,这个属性应该从接口调用OnPropertyChanged
方法来更新属性,在XAML中应该是:
local:CloseBehavior.CloseWhen="{Binding Path=ExitFlag, Mode=TwoWay}"
很抱歉,在尝试精简此示例的代码时,这是一个输入错误!将更新您误解的问题
UpdateSourceTrigger=PropertyChanged
。当绑定目标的属性更改时,此选项告知绑定更新视图模型(即绑定源)。在OP的情况下,绑定目标永远不会更改属性。因此,UpdateSourceTrigger
在这里是无用的,并且它与视图模型中的INPC
实现无关。很抱歉,在尝试精简此示例的代码时,这是一个输入错误!将更新您误解的问题UpdateSourceTrigger=PropertyChanged
。当绑定目标的属性更改时,此选项告知绑定更新视图模型(即绑定源)。在OP的情况下,绑定目标永远不会更改属性。因此,UpdateSourceTrigger
在这里是无用的,并且它与视图模型中的INPC
实现无关。很抱歉,在尝试精简此示例的代码时,这是一个输入错误!将更新您误解的问题UpdateSourceTrigger=PropertyChanged
。当绑定目标的属性更改时,此选项告知绑定更新视图模型(即绑定源)。在OP的情况下,绑定目标永远不会更改属性。因此,UpdateSourceTrigger
在这里是无用的,并且它与视图模型中的INPC
实现无关。很抱歉,在尝试精简此示例的代码时,这是一个输入错误!将更新问题