如何在设置其数据上下文时使用用户控件依赖项 属性?
How to use a user control dependency property when setting its data context?
我制作了一个用户控件,其中包含一个命令,可以调用它来响应某个事件。此命令是一个依赖项 属性。我想像这样在主要 window 中使用它:
<local:myUserControl Command="{Binding someCommand}"/>
"myCommand" 是我为此用户控件创建的依赖关系 属性。我将它绑定到主视图模型的命令 window ("someCommand").
问题是我正在设置我的用户控件的数据上下文(我有一个视图模型),它似乎将 "Command" 重置为空...这是我视图的代码隐藏型号:
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" 依赖项 属性 在我的用户控件中…
为了确保我提供最多的信息,我在主 window 的视图模型中有以下代码:
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 class 是标准 RelayCommand class,带有 "Predicate" CanExecute 和“Action Execute”。
我希望这个问题不是重复的……我发现了几个类似的问题,但他们似乎没有回答我的……
对于这个实际上有点愚蠢的问题,我真的很抱歉。我不太了解绑定过程中会发生什么。我认为 MainWindow 中的这段代码行......
<local:myUserControl Command="{Binding someCommand}"/>
…会尝试将 UserControl 的 "Command" 属性 绑定到 MainWindow 的数据上下文的 "someCommand"。事实上,正如@elgonzo 指出的那样,绑定在 UserControl 的 数据上下文中查找 "someCommand" 属性(而不是在 MainWindow 的数据上下文中!!)。因此,用这一行设置 UserControl 的数据上下文…
this.DataContext = new myViewModel();
...阻止正确完成绑定(因为它查找用户控件数据上下文的 "someCommand" 属性,现在是 "myViewModel",其中不包含"someCommand"...).
为了解决这个问题,我必须像这样更改绑定:
<local:myUserControl Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}},
Path=DataContext.someCommand}"/>
我在这里找到了这个解决方案:。
也许这不是最好的方法("Path= DataContext. someCommand" 让我这么想,它看起来不太优雅),但它确实有效。另一种方法是命名 MainWindow (x:Name="someName"),这样绑定就更简单了:
<local:myUserControl Command="{Binding ElementName=someName, Path=DataContext.someCommand}"/>
再次抱歉,非常感谢@elgonzo。
我制作了一个用户控件,其中包含一个命令,可以调用它来响应某个事件。此命令是一个依赖项 属性。我想像这样在主要 window 中使用它:
<local:myUserControl Command="{Binding someCommand}"/>
"myCommand" 是我为此用户控件创建的依赖关系 属性。我将它绑定到主视图模型的命令 window ("someCommand").
问题是我正在设置我的用户控件的数据上下文(我有一个视图模型),它似乎将 "Command" 重置为空...这是我视图的代码隐藏型号:
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" 依赖项 属性 在我的用户控件中…
为了确保我提供最多的信息,我在主 window 的视图模型中有以下代码:
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 class 是标准 RelayCommand class,带有 "Predicate" CanExecute 和“Action Execute”。
我希望这个问题不是重复的……我发现了几个类似的问题,但他们似乎没有回答我的……
对于这个实际上有点愚蠢的问题,我真的很抱歉。我不太了解绑定过程中会发生什么。我认为 MainWindow 中的这段代码行......
<local:myUserControl Command="{Binding someCommand}"/>
…会尝试将 UserControl 的 "Command" 属性 绑定到 MainWindow 的数据上下文的 "someCommand"。事实上,正如@elgonzo 指出的那样,绑定在 UserControl 的 数据上下文中查找 "someCommand" 属性(而不是在 MainWindow 的数据上下文中!!)。因此,用这一行设置 UserControl 的数据上下文…
this.DataContext = new myViewModel();
...阻止正确完成绑定(因为它查找用户控件数据上下文的 "someCommand" 属性,现在是 "myViewModel",其中不包含"someCommand"...).
为了解决这个问题,我必须像这样更改绑定:
<local:myUserControl Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}},
Path=DataContext.someCommand}"/>
我在这里找到了这个解决方案:。
也许这不是最好的方法("Path= DataContext. someCommand" 让我这么想,它看起来不太优雅),但它确实有效。另一种方法是命名 MainWindow (x:Name="someName"),这样绑定就更简单了:
<local:myUserControl Command="{Binding ElementName=someName, Path=DataContext.someCommand}"/>
再次抱歉,非常感谢@elgonzo。