【发布时间】:2019-11-16 16:59:54
【问题描述】:
我已经制作了一个包含命令的用户控件,该控件将被调用以响应某个事件。该命令是一个依赖属性。我想像这样在主窗口中使用它:
<local:myUserControl Command="{Binding someCommand}"/>
“myCommand”是我为此用户控件创建的依赖属性。我将它绑定到主窗口的视图模型的命令(“someCommand”)。
问题是我正在设置我的用户控件的数据上下文(我有一个视图模型),它似乎将“命令”重置为空......这是我的视图模型的代码隐藏:
public partial class myUserControl : UserControl, ICommandSource
{
public myUserControl()
{
this.DataContext = new myViewModel();
InitializeComponent();
}
public ICommand Command
{
get { return (ICommand)GetValue(CommandProperty); }
set { SetValue(CommandProperty, value); }
}
public static readonly DependencyProperty CommandProperty =
DependencyProperty.Register("Command", typeof(ICommand), typeof(myUserControl), new PropertyMetadata(null));
public object CommandParameter
{
get { return (object)GetValue(CommandParameterProperty); }
set { SetValue(CommandParameterProperty, value); }
}
public static readonly DependencyProperty CommandParameterProperty =
DependencyProperty.Register("CommandParameter", typeof(object), typeof(myUserControl), new PropertyMetadata(0));
public IInputElement CommandTarget
{
get { return (IInputElement)GetValue(CommandTargetProperty); }
set { SetValue(CommandTargetProperty, value); }
}
public static readonly DependencyProperty CommandTargetProperty =
DependencyProperty.Register("CommandTarget", typeof(IInputElement), typeof(myUserControl), new PropertyMetadata(null));
private void TextBlock_MouseUp(object sender, MouseButtonEventArgs e)
{
Command.Execute(this.CommandParameter);
}
}
我的用户控件的代码可能如下:
<UserControl x:Class="myApp.myUserControl"
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:myApp"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<TextBlock MouseUp="TextBlock_MouseUp">
</TextBlock>
</Grid>
</UserControl>
(我知道这个元素看起来有点傻(或没用),但我已经简化了它以测试什么不起作用,也为了提出一个相当简单的问题)。
我发现,如果我评论“this.DataContext = new myViewModel();”行,与命令的绑定完美运行。当我取消注释这一行并在“TextBlock_MouseUp”中放置一个断点时,“Command”属性等于 null...
有办法解决这个问题吗?我的视图模型中有一些复杂的代码(所以我不得不保留这一行“this.DataContext = new myViewModel();”),而且我不确定是否能找到除“Command”依赖之外的其他解决方案我的用户控件中的属性...
为了确保提供最多的信息,我在主窗口的视图模型中有以下代码:
public ICommand someCommand { get; set; }
//Constructor
public MainWindowViewModel()
{
this.someCommand = new RelayCommand((obj) => { return true; },
(obj) =>
{
//I put a breakpoint here
int dummy = 0;
});
}
(RelayCommand 类是标准的 RelayCommand 类,具有“Predicate” CanExecute 和“Action Execute”)。
我希望这个问题不是重复的……我找到了几个类似的问题,但他们似乎没有回答我的问题……
【问题讨论】:
-
未明确指定绑定源对象的绑定将查看 DataContext 属性提供的对象。请注意,DataContext 属性是一个继承 属性。如果您没有在用户控件中设置 DataContext,那么那里的命令绑定将使用从其父容器 DataContext“继承”的任何对象 DataContext。因此,基本上在用户控件中设置与不设置 DataContext 会更改绑定将尝试访问“someCommand”属性的对象。如果您的 myViewModel 实例没有“someCommand”属性:null
-
aha,所以@elgonzo 这意味着即使我在MainWindow 中设置
Command="{Binding someCommand}"绑定,它也会在UserControl 中查找的数据上下文?因此,如果我不设置 UserControl 的 DataContext,它会继承 MainWindow 中的一个,确实包含一些命令,但如果我设置 UserControl 的 DataContext,它不会继承 MainWindow 数据上下文,所以不再包含 someCommand 了?对吗? -
是的,除非您为绑定明确指定某个源,否则在尝试解析给定路径/属性(“someCommand”)时,绑定将查找绑定目标对象的 DataContext。在您的情况下,绑定目标是用户控件的
CommandDependencyProperty,因此绑定将尝试在用户控件的 DataContext 提供的对象中查找“someCommand”属性。您在上一条评论中所说的一切都是正确的。 :-) -
@elgonzo 哦哦!非常感谢!请为缺乏知识道歉:似乎我不太了解绑定是如何制作的……再次感谢!你想为此做一个答案(以获得一些分数),还是我应该用最终有效的代码来编写它?
-
随意使用您的代码示例进行自我回答(自我回答问题完全可以。谁写答案并不重要。)顺便说一句,我只是在Binding.Source 的官方文档和微软自己的 WPF 绑定指南/概述,我很惊讶没有找到任何说明这种“默认源”行为的内容。不过,我只是在浏览文档,所以也许我只是忽略了一些东西。 (如果你不回答,当我能找到一些关于它的参考文档时,我会在周末的某个时候写一个答案)
标签: c# xaml mvvm user-controls dependency-properties