【发布时间】:2017-02-27 15:08:51
【问题描述】:
我创建了一个UserControl 作为文件浏览工具,我想将Commands 实现为DependencyProperties 以进行加载和保存,以便我可以从我的ViewModel 绑定Commands 以处理它们。
现在的问题是,如果我使用预定义的 Commands 像 Open 或 Save 并在我的 Window 中处理它们,它可以工作,但如果我使用 Bindingsfrom 我的 ViewModel 这些 Commands是null...
以下代码是一个示例程序,我删除了对我的问题不重要的所有内容,因为它的代码太多了。
用户控制
XAML
<UserControl x:Class="WpfApplication1.TestControl"
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:local="clr-namespace:WpfApplication1"
xmlns:models="clr-namespace:WpfApplication1.Models"
Height="21" Width="80" Margin="2">
<UserControl.Resources>
<models:UserControlViewModel x:Key="ViewModel"/>
</UserControl.Resources>
<UserControl.DataContext>
<Binding Source="{StaticResource ViewModel}"/>
</UserControl.DataContext>
<Grid>
<Button Content="_Load" IsDefault="True"
Command="{Binding Path=ExecuteCommand, Source={StaticResource ViewModel}}"
CommandParameter="{Binding Path=LoadCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType ={x:Type local:TestControl}}}"/>
</Grid>
代码隐藏
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace WpfApplication1
{
public partial class TestControl : UserControl
{
public static readonly DependencyProperty LoadCommandProperty = DependencyProperty.Register(nameof(LoadCommand), typeof(ICommand), typeof(TestControl), new PropertyMetadata(null));
public ICommand LoadCommand
{
get { return (ICommand)GetValue(LoadCommandProperty); }
set { SetValue(LoadCommandProperty, value); }
}
public TestControl()
{
InitializeComponent();
}
}
}
视图模型
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Input;
using Prism.Commands;
namespace WpfApplication1.Models
{
public class UserControlViewModel
: INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public DelegateCommand<ICommand> ExecuteCommand { get; }
private void ExecuteCommand_Executed(ICommand cmd) => cmd?.Execute("C:\\Test.txt");
private void Notify([CallerMemberName] string name = null)
{
if (name != null)
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
public UserControlViewModel()
{
ExecuteCommand = new DelegateCommand<ICommand>(ExecuteCommand_Executed);
}
}
}
窗口
XAML
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication1"
xmlns:models="clr-namespace:WpfApplication1.Models"
mc:Ignorable="d"
Title="MainWindow" Height="200" Width="200">
<Window.Resources>
<models:MainWindowViewModel x:Key="ViewModel"/>
</Window.Resources>
<Window.DataContext>
<Binding Source="{StaticResource ViewModel}"/>
</Window.DataContext>
<Window.CommandBindings>
<CommandBinding Command="Open" Executed="CommandBinding_Executed"/>
</Window.CommandBindings>
<StackPanel VerticalAlignment="Center">
<local:TestControl LoadCommand="{Binding Path=OpenCommand, Source={StaticResource ViewModel}}"/>
<local:TestControl LoadCommand="Open"/>
</StackPanel>
</Window>
代码隐藏
using System.Windows;
namespace WpfApplication1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void CommandBinding_Executed(object sender, System.Windows.Input.ExecutedRoutedEventArgs e)
{
MessageBox.Show($"Window: {e.Parameter.ToString()}");
}
}
}
视图模型
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
using Prism.Commands;
namespace WpfApplication1.Models
{
public class MainWindowViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public DelegateCommand<string> OpenCommand { get; }
private void OpenCommand_Executed(string file)
{
MessageBox.Show($"Model: {file}");
}
private void Notify([CallerMemberName] string name = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
public MainWindowViewModel()
{
OpenCommand = new DelegateCommand<string>(OpenCommand_Executed);
}
}
}
该窗口包含一个预定义的Open Command,这种方式有效,但Binding 无效。
要运行此应用程序,您需要 Prism.Wpf NuGet 包。
【问题讨论】:
-
收到 MVCE 后给我回复。了解全貌后应该不会那么难。
-
您没有在 ViewModel 中分配命令。如果您使用的是发布的,则为空。此外,此时命令工作应该存在于 ViewModel 中,并且您仍在为命令使用代码。基本上,如果您想向控件添加命令,那么只需在包装浏览器的自定义控件中创建 ICommand(复制 ViewModel 中的代码)或将逻辑放入 ViewModel 中。如果我错了,请发布所有代码,以便我可以看到完整的图片。
-
Shoot me a reply- 这是通过使用 @EdPlunkett - 评论中带有at字符的名称来完成的。 -
谢谢@Vojtěch Dohnal。
-
@Michael Puckett II 现在你可以看到全图了。
标签: c# wpf xaml viewmodel commandbinding