[英]UserControl with command-property
I have a UserControl
for a LinkLabel
with an Image before. 我以前有一个带有图像的LinkLabel
的UserControl
。
The XAML looks like: XAML看起来像:
<UserControl>
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Source={x:Static helper:ImageHelper.JumpLabelImage}}" Width="16" Height="16" VerticalAlignment="Center"/>
<TextBlock >
<Hyperlink Command="{Binding JumpCommand, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
CommandParameter="{Binding CommandParameter, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" >
<TextBlock Text="{Binding LabelText, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" VerticalAlignment="Center" />
</Hyperlink>
</TextBlock>
</StackPanel>
</UserControl>
The DataContext of this UserControl
is set to the CodeBehind-File. 此UserControl
的DataContext设置为CodeBehind-File。
The Code-Behind-File looks like: 代码隐藏文件如下所示:
public partial class JumpLabel : UserControl
{
public static readonly DependencyProperty LabelTextProperty = DependencyProperty.Register("LabelText", typeof(string), typeof(JumpLabel));
public static readonly DependencyProperty JumpCommandProperty = DependencyProperty.Register("JumpCommand", typeof(ICommand), typeof(JumpLabel));
public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register("CommandParameter", typeof(object), typeof(JumpLabel));
public string LabelText
{
get { return (string)GetValue(LabelTextProperty); }
set { SetValue(LabelTextProperty, value); }
}
public ICommand JumpCommand
{
get { return (ICommand)GetValue(JumpCommandProperty); }
set { SetValue(JumpCommandProperty, value); }
}
public object CommandParameter
{
get { return GetValue(CommandParameterProperty); }
set { SetValue(CommandParameterProperty, value); }
}
public JumpLabel()
{
InitializeComponent();
}
}
Now I want to call the JumpCommand if the user clicks on the LinkLabel
现在,如果用户单击LinkLabel
我想调用JumpCommand
Therefor I use the following code to assign the Command in the view of my MainWindow: 为此,我使用以下代码在MainWindow的视图中分配Command:
<view:JumpLabel LabelText="Extensions" JumpCommand="{Binding JumpLabelCommand, UpdateSourceTrigger=PropertyChanged}" CommandParameter="{Binding ElementName=control}"/>
In the ViewModel of my MainWindow I have: 在我的MainWindow的ViewModel中,我有:
private ICommand _jumpLabelCommand;
public ICommand JumpLabelCommand
{
get { return _jumpLabelCommand; }
set
{
_jumpLabelCommand = value;
OnPropertyChanged();
}
}
and 和
public MainWindowViewModel()
{
_mainWindowModel = new MainWindowModel();
JumpLabelCommand = new RelayCommand(DummyExecute);
}
private void DummyExecute(object parameter)
{
}
In the DummyExecute I have a Breakpoint which is never reached. 在DummyExecute中,我有一个从未达到的断点。 I'm not getting it why my Command doesn't work. 我不明白为什么我的命令不起作用。 What am I doing wrong? 我究竟做错了什么?
Update: 更新:
I've created a new small project with focus on the binding-problem for the Command-Property in the UserControl
. 我创建了一个新的小项目,重点关注UserControl
Command-Property的绑定问题。
The MainWindowView is: MainWindowView是:
<Window x:Class="UCWithDP.View.MainWindowView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:viewModel="clr-namespace:UCWithDP.ViewModel"
xmlns:view="clr-namespace:UCWithDP.View"
Title="MainWindowView" Height="300" Width="600">
<Window.DataContext>
<viewModel:MainWindowViewModel/>
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Label Grid.Row="0" Content="{Binding SomeText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<view:JumpLabel Grid.Row="1" JumpLabelText="My Jump Label" JumpCommand="{Binding DoJumpCommand, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<Button Grid.Row="2" Content="Some Button" Command="{Binding DoJumpCommand}"/>
</Grid>
</Window>
The MainWindowViewModel is: MainWindowViewModel是:
internal class MainWindowViewModel : ViewModelBase
{
private string _someText;
private ICommand doJumpCommand;
public MainWindowViewModel()
{
SomeText = "Hello from ViewModel";
DoJumpCommand = new RelayCommand(DoJumpExecute);
}
public string SomeText
{
get { return _someText; }
set
{
_someText = value;
OnPropertyChanged();
}
}
public ICommand DoJumpCommand
{
get { return doJumpCommand; }
set
{
doJumpCommand = value;
OnPropertyChanged();
}
}
private void DoJumpExecute(object parameter)
{
}
}
My UserControl
is: 我的UserControl
是:
<UserControl x:Class="UCWithDP.View.JumpLabel"
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"
mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300" Height="20"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
x:Name="uc">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="X" FontWeight="Bold" VerticalAlignment="Center" Margin="2"/>
<TextBlock Grid.Column="1" Margin="2">
<Hyperlink Command="{Binding ElementName=uc, Path=JumpCommand, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<TextBlock Text="{Binding JumpLabelText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Center"/>
</Hyperlink>
</TextBlock>
</Grid>
</UserControl>
The code-behind of the UserControl
is UserControl
的代码背后是
public partial class JumpLabel : UserControl
{
public static readonly DependencyProperty JumpLabelTextProperty = DependencyProperty.Register(
"JumpLabelText", typeof (string), typeof (JumpLabel), new PropertyMetadata(default(string)));
public static readonly DependencyProperty JumpCommandProperty = DependencyProperty.Register(
"JumpCommand", typeof (ICommand), typeof (JumpLabel), new PropertyMetadata(default(ICommand)));
public JumpLabel()
{
InitializeComponent();
}
public ICommand JumpCommand
{
get { return (ICommand) GetValue(JumpCommandProperty); }
set { SetValue(JumpCommandProperty, value); }
}
public string JumpLabelText
{
get { return (string) GetValue(JumpLabelTextProperty); }
set { SetValue(JumpLabelTextProperty, value); }
}
}
In the MainWindowView the Command-Property of my UserControl
and a Button
are binded to the same ICommand
. 在MainWindowView中,我的UserControl
的Command-Property和一个Button
绑定到相同的ICommand
。 If I click the Button
my Breakpoint in DoJumpExecute is reached. 如果我单击Button
,将达到DoJumpExecute中的断点。 If I click on the HyperLink
the Breakpoint is not reached. 如果单击HyperLink
,则无法达到断点。
I still don't understand it... 我还是不明白...
Solution 解
In my MainWindowView now I use the following code 现在在我的MainWindowView中,使用以下代码
<view:JumpLabel Grid.Row="1" JumpLabelText="My Jump Label"
JumpCommand="{Binding DataContext.DoJumpCommand, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged,
RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}"/>
and now it works. 现在可以了。
Judging by the code that you have provided, you could have any number of problems... assuming that you actually have all of the properties that you are using correctly defined, these are the most likely causes of error: 从提供的代码来看,您可能会遇到许多问题……假设您实际上拥有正确使用的所有定义属性,这些是最有可能导致错误的原因:
Firstly, when data binding from a UserControl
XAML page to its properties, you should get used to using the RelativeSource Binding
, despite its verbosity. 首先,从UserControl
XAML页面到其属性的数据绑定时,尽管它很冗长,但您应该习惯于使用RelativeSource Binding
。 Note that you should do this instead of setting the UserControl.DataContext
to its code behind: 请注意,您应该这样做, 而不是将UserControl.DataContext
设置为后面的代码:
<Hyperlink Command="{Binding JumpCommand, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}" CommandParameter="{Binding CommandParameter,
RelativeSource={RelativeSource AncestorType={x:Type YourPrefix:YourUserControl}},
Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<TextBlock Text="{Binding LabelText, RelativeSource={RelativeSource AncestorType={
x:Type YourPrefix:YourUserControl}, UpdateSourceTrigger=PropertyChanged,
Mode=TwoWay}" VerticalAlignment="Center" />
</Hyperlink>
Next, you have this line of code: 接下来,您有以下代码行:
<view:JumpLabel LabelText="Extensions" JumpCommand="{Binding JumpLabelCommand,
UpdateSourceTrigger=PropertyChanged}" CommandParameter="{Binding ElementName=
control}" />
This will of course not work if any of the following conditions are true: 如果满足以下任何条件,那么这当然将不起作用:
ICommand
property named JumpLabelCommand
in your bound view model, or code behind. 您的绑定视图模型中没有名为JumpLabelCommand
的ICommand
属性,也没有后面的代码。 control
in your view. 您的视图中没有名为control
的UI控件。 DataContext
of the UI control named control
does not have a suitable value to use as the CommandParameter
property... perhaps this Binding
should have been: CommandParameter="{Binding Propertyname, ElementName=control}"
? UI控件( control
的DataContext
没有适合用作CommandParameter
属性的值...也许此Binding
应该是: CommandParameter="{Binding Propertyname, ElementName=control}"
? If none of the above conditions are true and you are still having problems, then please edit your question and provide all of the relevant code , which should include everything that is relevant, eg. 如果上述条件都不成立,并且您仍然遇到问题,请编辑问题并提供所有相关代码 ,其中应包括所有相关内容,例如。 details of the control
element, it's set DataContext
, etc. control
元素的详细信息,例如DataContext
等。
this is more a general answer: if you create a usercontrol with dependency properties then your binding should always contain some kind of "relative binding" - i always use elementname binding. 这是一个更通用的答案:如果您创建具有依赖项属性的用户控件,则您的绑定应始终包含某种“相对绑定”-我始终使用elementname绑定。 so your usercontrol binding should look like this. 因此您的usercontrol绑定应如下所示。
<UserControl x:Name="uc">
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Source={x:Static helper:ImageHelper.JumpLabelImage}}" Width="16" Height="16" VerticalAlignment="Center"/>
<TextBlock >
<Hyperlink Command="{Binding ElementName=uc, Path=JumpCommand, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
CommandParameter="{Binding ElementName=uc, Path=CommandParameter, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" >
<TextBlock Text="{Binding ElementName=uc, Path=LabelText, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" VerticalAlignment="Center" />
</Hyperlink>
</TextBlock>
</StackPanel>
</UserControl>
if you set the datacontext for your usercontrol to self, then you break the datacontext inheriting and that is not what you want. 如果将用户控件的datacontext设置为self,则将中断datacontext继承,而这不是您想要的。 so you have to remove all kinds of setting the datacontext to self within your usercontrol. 因此,您必须在用户控件中删除所有将datacontext设置为self的设置。
the updatesource trigger are used to handle the update to the source, thats why your updatesource trigger makes no sense in your usercontrol. updatesource触发器用于处理对源的更新,这就是为什么updatesource触发器在用户控件中毫无意义的原因。 eg a textblock cant updatethe Text property to source - it would work with a textbox :) 例如,文本块无法将Text属性更新为源-它可以与文本框一起使用:)
your constructor of JumpLabel Control should be 您的JumpLabel控件的构造函数应为
public JumpLabel()
{
InitializeComponent();
this.DataContext=new MainWindowViewModel();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.