[英]How to use a user control dependency property when setting its data context?
I've made a user control which contains a command, to be called in response to a certain event. 我创建了一个包含命令的用户控件,以响应某个事件而调用。 This command is a dependency property.
此命令是依赖项属性。 I want to use it in the main window like this:
我想在主窗口中使用它,如下所示:
<local:myUserControl Command="{Binding someCommand}"/>
The "myCommand" is the dependency property I created for this user control. “myCommand”是我为此用户控件创建的依赖项属性。 And I bind it to a command of the view model of the main window ("someCommand").
然后我将它绑定到主窗口的视图模型的命令(“someCommand”)。
The problem is that I am setting the datacontext of my usercontrol (I have a view model for it), and it seems to reset the "Command" to null… Here is the code-behind of my view model: 问题是我正在设置我的usercontrol的datacontext(我有一个视图模型),它似乎将“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);
}
}
The code of my user control could be the Following: 我的用户控件的代码可能是以下内容:
<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>
(I know that this element seems a bit silly (or useless), but I have simplified it to test what didn't worked and also in order to ask a rather simple question). (我知道这个元素看起来有点愚蠢(或无用),但我已经简化它来测试什么没有用,也是为了问一个相当简单的问题)。
I have discovered that, if I comment the "this.DataContext = new myViewModel();" 我发现,如果我评论“this.DataContext = new myViewModel();” line, the binding to the command works perfectly.
对命令的绑定工作完美。 And when I uncomment this line and put a breakpoint in the "TextBlock_MouseUp", the "Command" property is equal to null...
当我取消注释这一行并在“TextBlock_MouseUp”中放置一个断点时,“Command”属性等于null ...
Would there be a way to resolve this problem? 有没有办法解决这个问题? I have some complicated code in my view model (so I'm quite forced to keep this line "this.DataContext = new myViewModel();"), and I am not sure I could find another solution than having a "Command" dependency property in my user control…
我的视图模型中有一些复杂的代码(所以我非常强迫这行“this.DataContext = new myViewModel();”),我不确定我能找到另一个解决方案,而不是“命令”依赖我的用户控件中的属性...
To be sure I give a maximum of informations, I have the following code in the view model of my main 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;
});
}
(The RelayCommand class is a standard RelayCommand class, with a "Predicate" CanExecute and an "Action Execute). (RelayCommand类是标准的RelayCommand类,带有“Predicate”CanExecute和“Action Execute”。
I hope this question is not a duplicate… I have found several similar question, but they did not seem to answer mine... 我希望这个问题不重复......我发现了几个类似的问题,但他们似乎没有回答我的问题......
I'm really sorry for this question which was in fact a bit silly. 我真的很抱歉这个问题实际上有点傻。 I hadn't understand very well what happens during a binding.
我不太了解绑定期间会发生什么。 I thought that this code line in the MainWindow…
我认为MainWindow中的这段代码行......
<local:myUserControl Command="{Binding someCommand}"/>
…would have made an attempt to bind the UserControl's "Command" property to the "someCommand" of the datacontext of the MainWindow . ...会尝试将UserControl的“Command”属性绑定到MainWindow的datacontext的“someCommand”。 In fact, as @elgonzo pointed out, the binding looks up in the UserControl's datacontext for the "someCommand" property (and not in the MainWindow's datacontext!!).
事实上,正如@elgonzo指出的那样,绑定在UserControl的 datacontext中查找“someCommand”属性(而不是在MainWindow的datacontext !!中)。 Therefore, setting the UserControl's datacontext with this line…
因此,使用此行设置UserControl的datacontext ...
this.DataContext = new myViewModel();
...was preventing the binding to be correctly done (since it looks for the "someCommand" property of the UserControl's datacontext, which is now "myViewModel", which does not contain "someCommand"...). ...阻止绑定正确完成(因为它查找UserControl的datacontext的“someCommand”属性,现在是“myViewModel”,它不包含“someCommand”...)。
To fix this, I had to change the binding like this: 要解决这个问题,我必须像这样更改绑定:
<local:myUserControl Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}},
Path=DataContext.someCommand}"/>
I've found this solution here: https://stackoverflow.com/a/1127964/11609068 . 我在这里找到了这个解决方案: https : //stackoverflow.com/a/1127964/11609068 。
Maybe it is not the best way to do it (the "Path= DataContext. someCommand" make me think this, it doesn't seem very elegant), but it works. 也许它不是最好的方法(“Path = DataContext。someCommand ”让我觉得这个,它看起来并不优雅),但它确实有效。 Another way to do it is to name the MainWindow (x:Name="someName"), so that the binding is a bit simpler:
另一种方法是命名MainWindow(x:Name =“someName”),以便绑定更简单:
<local:myUserControl Command="{Binding ElementName=someName, Path=DataContext.someCommand}"/>
Again, sorry and many thanks to @elgonzo. 再次,抱歉,非常感谢@elgonzo。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.