命令参数始终为 NULL
CommandParameter is always NULL
我想在 WPF 中实现一个简单的关闭按钮 Window。 Window 基本上是这样的:
<Window x:Class="MyApplication.MainWindow"
xmlns=""....
...."
Title="MainWindow" WindowState="Maximized" WindowStartupLocation="CenterScreen" x:Name="mainWindow">
<DockPanel LastChildFill="True">
<Ribbon DockPanel.Dock="Top">
<Ribbon.ApplicationMenu>
<RibbonApplicationMenu SmallImageSource="Resources/menu_16x16.png">
<RibbonApplicationMenu.FooterPaneContent>
<RibbonButton Label="Beenden"
Command="{Binding CmdCloseApp}"
CommandParameter="{Binding ElementName=mainWindow}"
SmallImageSource="Resources/ende_16x16.png"
HorizontalAlignment="Right"/>
</RibbonApplicationMenu.FooterPaneContent>
</RibbonApplicationMenu>
</Ribbon.ApplicationMenu>
</Ribbon>
</DockPanel>
</Window>
此 Window 的 DataContext 在其代码隐藏中设置为 MainWindowViewModel
的一个实例
主要Window视图模型:
public class MainWindowViewModel
{
public ICommand CmdCloseApp { get; set; }
public MainWindowViewModel()
{
CmdCloseApp = new RelayCommand<Window>(CloseApp);
}
public void CloseApp(Window w)
{
w.Close();
}
}
在 CloseApp
w 中始终为空。 Alle 其他带有字符串参数等的命令。工作完美 - 我唯一的问题是我没有得到 window 元素没有找到我的视图模型的方法。
感谢您的帮助!
编辑
很抱歉,我用一个简单的按钮试了一下,它起作用了——这个问题只发生在RibbonButton
编辑: 在您更改为应用程序菜单 RibbonButton 之后,您的问题是 Microsoft RibbonControlLibrary 使用弹出菜单来按住按钮,而 MainWindow 不是的一部分(父级)弹出菜单的可视化树,因此您的 ElementName 绑定无法找到 "mainWindow" window,因此它将 null 分配给 CommandParameter
您可以使用 static Application.Current 获取主窗口,然后它将起作用。
注意! MainWindow 是应用程序 属性 的名称,而不是您的 window
的名称
<Window x:Class="WpfRelayCommandParameter.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:wpfRelayCommandParameter="clr-namespace:WpfRelayCommandParameter"
xmlns:ribbon="http://schemas.microsoft.com/winfx/2006/xaml/presentation/ribbon"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance wpfRelayCommandParameter:MainWindowViewModel}"
Title="MainWindow" Height="350" Width="525"
x:Name="mainWindow">
<DockPanel LastChildFill="True">
<DockPanel LastChildFill="True">
<ribbon:Ribbon DockPanel.Dock="Top">
<ribbon:Ribbon.ApplicationMenu>
<ribbon:RibbonApplicationMenu SmallImageSource="Resources/AppMenu.png">
<ribbon:RibbonApplicationMenu.FooterPaneContent>
<ribbon:RibbonButton Label="Beenden"
Command="{Binding CmdCloseApp}"
CommandParameter="{Binding MainWindow, Source={x:Static Application.Current}}"
SmallImageSource="Resources/Exit.png"
HorizontalAlignment="Right" Click="ButtonBase_OnClick"/>
</ribbon:RibbonApplicationMenu.FooterPaneContent>
</ribbon:RibbonApplicationMenu>
</ribbon:Ribbon.ApplicationMenu>
</ribbon:Ribbon>
</DockPanel>
</DockPanel>
我个人更喜欢 window 的回调,通过一个可以根据您的视图模型需求自定义的接口,并且可以在单元测试中模拟:
<Window x:Class="WpfRelayCommandParameter.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:wpfRelayCommandParameter="clr-namespace:WpfRelayCommandParameter"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance wpfRelayCommandParameter:MainWindowViewModel}"
Title="MainWindow" Height="350" Width="525"
x:Name="mainWindow">
<Grid>
<Button Content="Close Window"
Command="{Binding CmdCloseApp}"
VerticalAlignment="Top"
HorizontalAlignment="Left" />
</Grid>
代码
public partial class MainWindow : Window, IMainWindow
{
public MainWindow()
{
DataContext = new MainWindowViewModel(this);
InitializeComponent();
}
}
public interface IMainWindow
{
void Close();
}
public class MainWindowViewModel
{
private readonly IMainWindow _mainWindow;
public MainWindowViewModel() : this(null)
{
// Design time
}
public MainWindowViewModel(IMainWindow mainWindow)
{
_mainWindow = mainWindow;
CmdCloseApp = new RelayCommand(CloseApp);
}
public ICommand CmdCloseApp { get; set; }
public void CloseApp(object parameter)
{
_mainWindow.Close();
}
}
注意 CanExecute 的类型和 null 可能存在的问题 CanExecute on RelayCommand
我想在 WPF 中实现一个简单的关闭按钮 Window。 Window 基本上是这样的:
<Window x:Class="MyApplication.MainWindow"
xmlns=""....
...."
Title="MainWindow" WindowState="Maximized" WindowStartupLocation="CenterScreen" x:Name="mainWindow">
<DockPanel LastChildFill="True">
<Ribbon DockPanel.Dock="Top">
<Ribbon.ApplicationMenu>
<RibbonApplicationMenu SmallImageSource="Resources/menu_16x16.png">
<RibbonApplicationMenu.FooterPaneContent>
<RibbonButton Label="Beenden"
Command="{Binding CmdCloseApp}"
CommandParameter="{Binding ElementName=mainWindow}"
SmallImageSource="Resources/ende_16x16.png"
HorizontalAlignment="Right"/>
</RibbonApplicationMenu.FooterPaneContent>
</RibbonApplicationMenu>
</Ribbon.ApplicationMenu>
</Ribbon>
</DockPanel>
</Window>
此 Window 的 DataContext 在其代码隐藏中设置为 MainWindowViewModel
主要Window视图模型:
public class MainWindowViewModel
{
public ICommand CmdCloseApp { get; set; }
public MainWindowViewModel()
{
CmdCloseApp = new RelayCommand<Window>(CloseApp);
}
public void CloseApp(Window w)
{
w.Close();
}
}
在 CloseApp
w 中始终为空。 Alle 其他带有字符串参数等的命令。工作完美 - 我唯一的问题是我没有得到 window 元素没有找到我的视图模型的方法。
感谢您的帮助!
编辑
很抱歉,我用一个简单的按钮试了一下,它起作用了——这个问题只发生在RibbonButton
编辑: 在您更改为应用程序菜单 RibbonButton 之后,您的问题是 Microsoft RibbonControlLibrary 使用弹出菜单来按住按钮,而 MainWindow 不是的一部分(父级)弹出菜单的可视化树,因此您的 ElementName 绑定无法找到 "mainWindow" window,因此它将 null 分配给 CommandParameter
您可以使用 static Application.Current 获取主窗口,然后它将起作用。
注意! MainWindow 是应用程序 属性 的名称,而不是您的 window
<Window x:Class="WpfRelayCommandParameter.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:wpfRelayCommandParameter="clr-namespace:WpfRelayCommandParameter"
xmlns:ribbon="http://schemas.microsoft.com/winfx/2006/xaml/presentation/ribbon"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance wpfRelayCommandParameter:MainWindowViewModel}"
Title="MainWindow" Height="350" Width="525"
x:Name="mainWindow">
<DockPanel LastChildFill="True">
<DockPanel LastChildFill="True">
<ribbon:Ribbon DockPanel.Dock="Top">
<ribbon:Ribbon.ApplicationMenu>
<ribbon:RibbonApplicationMenu SmallImageSource="Resources/AppMenu.png">
<ribbon:RibbonApplicationMenu.FooterPaneContent>
<ribbon:RibbonButton Label="Beenden"
Command="{Binding CmdCloseApp}"
CommandParameter="{Binding MainWindow, Source={x:Static Application.Current}}"
SmallImageSource="Resources/Exit.png"
HorizontalAlignment="Right" Click="ButtonBase_OnClick"/>
</ribbon:RibbonApplicationMenu.FooterPaneContent>
</ribbon:RibbonApplicationMenu>
</ribbon:Ribbon.ApplicationMenu>
</ribbon:Ribbon>
</DockPanel>
</DockPanel>
我个人更喜欢 window 的回调,通过一个可以根据您的视图模型需求自定义的接口,并且可以在单元测试中模拟:
<Window x:Class="WpfRelayCommandParameter.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:wpfRelayCommandParameter="clr-namespace:WpfRelayCommandParameter"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance wpfRelayCommandParameter:MainWindowViewModel}"
Title="MainWindow" Height="350" Width="525"
x:Name="mainWindow">
<Grid>
<Button Content="Close Window"
Command="{Binding CmdCloseApp}"
VerticalAlignment="Top"
HorizontalAlignment="Left" />
</Grid>
代码
public partial class MainWindow : Window, IMainWindow
{
public MainWindow()
{
DataContext = new MainWindowViewModel(this);
InitializeComponent();
}
}
public interface IMainWindow
{
void Close();
}
public class MainWindowViewModel
{
private readonly IMainWindow _mainWindow;
public MainWindowViewModel() : this(null)
{
// Design time
}
public MainWindowViewModel(IMainWindow mainWindow)
{
_mainWindow = mainWindow;
CmdCloseApp = new RelayCommand(CloseApp);
}
public ICommand CmdCloseApp { get; set; }
public void CloseApp(object parameter)
{
_mainWindow.Close();
}
}
注意 CanExecute 的类型和 null 可能存在的问题 CanExecute on RelayCommand