我已经制作了一个用户控件,其中包含一个命令,以响应特定事件而被调用。此命令是依赖项属性。我想像这样在主窗口中使用它:
<local:myUserControl Command="{Binding someCommand}"/>
“ myCommand”是我为此用户控件创建的依赖项属性。然后将其绑定到主窗口视图模型的命令(“ someCommand”)。
问题是我正在设置用户控件的数据上下文(我有一个视图模型),并且似乎将“ Command”重置为null…这是我的视图模型的代码:>
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类,带有“谓词” CanExecute和“动作执行”)。
我希望这个问题不会重复...我发现了几个类似的问题,但是他们似乎并没有回答我...
答案 0 :(得分:1)
对于这个问题,我真的很抱歉,这有点愚蠢。我不太了解绑定期间会发生什么。我以为这段代码在MainWindow中……
<local:myUserControl Command="{Binding someCommand}"/>
…将尝试将UserControl的“ Command”属性绑定到 MainWindow 的数据上下文的“ someCommand”。实际上,正如@elgonzo指出的那样,该绑定在 UserControl的数据上下文中查找“ someCommand”属性(而不是在MainWindow的datacontext中!)。因此,使用此行设置UserControl的数据上下文...
this.DataContext = new myViewModel();
...正在阻止正确完成绑定(因为它正在查找UserControl的数据上下文的“ someCommand”属性,现在为“ myViewModel”,其中不包含“ someCommand” ...)。
要解决此问题,我必须像这样更改绑定:
<local:myUserControl Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}},
Path=DataContext.someCommand}"/>
我在这里找到了此解决方案:https://stackoverflow.com/a/1127964/11609068。
也许这不是最好的方法(“ Path = DataContext。 someCommand”让我觉得这似乎不太优雅),但它确实有效。做到这一点的另一种方法是命名MainWindow(x:Name =“ someName”),这样绑定就更简单了:
<local:myUserControl Command="{Binding ElementName=someName, Path=DataContext.someCommand}"/>
再次对不起,非常感谢@elgonzo。