UserControl 的相对源绑定 [英] RelativeSource-Binding for UserControl

查看:34
本文介绍了UserControl 的相对源绑定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个 UserControl 用于在我的应用程序中显示超链接.

I've created a UserControl for displaying a Hyperlink in my application.

这个 UserControl 的标记看起来像:

The markup of this UserControl looks like:

<UserControl x:Class="MVVMExample.View.UserControls.ActionLink"
             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"
             DataContext="{Binding RelativeSource={RelativeSource Self}}">
    <Grid>
        <TextBlock Margin="5">
                <Hyperlink Command="{Binding LinkCommand}" CommandParameter="{Binding LinkCommandParameter}">
                    <TextBlock Text="{Binding LinkText, UpdateSourceTrigger=PropertyChanged}"/>
                </Hyperlink>
        </TextBlock>
    </Grid>
</UserControl>

UserControlDataContext 位于 CodeBehind 中,如下所示:

The DataContext of this UserControl is in the CodeBehind which looks like:

public partial class ActionLink : UserControl, INotifyPropertyChanged
{
    public static readonly DependencyProperty LinkTextProperty = DependencyProperty.Register(
        "LinkText", typeof (string), typeof (ActionLink), new PropertyMetadata(LinkTextChanged));

    public static readonly DependencyProperty LinkCommandParameterProperty = DependencyProperty.Register(
        "LinkCommandParameter", typeof (object), typeof (ActionLink),
        new PropertyMetadata(LinkCommandParameterChanged));

    public static readonly DependencyProperty LinkCommandProperty = DependencyProperty.Register(
        "LinkCommand", typeof (ICommand), typeof (ActionLink), new PropertyMetadata(LinkCommandChanged));

    public ActionLink()
    {
        InitializeComponent();
    }

    public object LinkCommandParameter
    {
        get { return GetValue(LinkCommandParameterProperty); }
        set { SetValue(LinkCommandParameterProperty, value); }
    }

    public string LinkText
    {
        get { return (string) GetValue(LinkTextProperty); }
        set
        {
            SetValue(LinkTextProperty, value);
            OnPropertyChanged();
        }
    }

    public ICommand LinkCommand
    {
        get { return (ICommand) GetValue(LinkCommandProperty); }
        set { SetValue(LinkCommandProperty, value); }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private static void LinkTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        ((ActionLink) d).LinkText = (string) e.NewValue;
    }

    private static void LinkCommandParameterChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        ((ActionLink) d).LinkCommandParameter = e.NewValue;
    }

    private static void LinkCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        ((ActionLink) d).LinkCommand = (ICommand) e.NewValue;
    }

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

一切正常.

现在,如果我想将此 UserControl 与命令绑定一起使用,我必须执行以下操作:

Now if I want to use this UserControl with the Command-Binding I have to do the following:

<userControls:ActionLink LinkText="View customers" LinkCommand="{Binding DataContext.ViewCustomersCommand, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}"/>

如果我使用 Button 代替,我不必提供那个 RelativeSource.是否有机会我也不必在自定义创建的 UserControl s 的绑定属性上提供 RelativeSource?

If I use a Button instead I don't have to provide that RelativeSource. Is there a opportunity that I also don't have to provide a RelativeSource on binding properties of custom created UserControls?

推荐答案

写作时

<userControls:ActionLink LinkCommand="{Binding ViewCustomersCommand}"/>

WPF 尝试在 UserControl 的 DataContext 中建立到 ViewCustomersCommand 属性的数据绑定,该属性通常从控件的父级继承,并保存对某个视图模型对象的引用.这在这里不起作用,因为您已将 DataContext 显式设置为 UserControl 实例.

WPF tries to establish a data binding to a ViewCustomersCommand property in the DataContext of your UserControl, which is usually inherited from the control's parent, and holds a reference to some view model object. This doesn't work here because you have explicitly set the DataContext to the UserControl instance.

一旦您的 UserControl 中具有可绑定属性(即依赖属性),您就不应设置其 DataContext.如果这样做,您将始终必须明确指定绑定源对象,因为不再继承 DataContext.

As soon as you have bindable properties (i.e. dependency properties) in your UserControl, you should not set its DataContext. If you do so, you will always have to specifiy the binding source objects explicitly, because the DataContext is no longer inherited.

所以删除

DataContext="{Binding RelativeSource={RelativeSource Self}}"

从您的 UserControl 的 XAML 设置并在其所有内部绑定中设置一个 RelativeSource:

setting from your UserControl's XAML and set a RelativeSource in all its internal bindings:

<Hyperlink
    Command="{Binding LinkCommand,
              RelativeSource={RelativeSource AncestorType=UserControl}}"
    CommandParameter="{Binding LinkCommandParameter,
                       RelativeSource={RelativeSource AncestorType=UserControl}}">
    <TextBlock
        Text="{Binding LinkText,
               RelativeSource={RelativeSource AncestorType=UserControl}}"/>
</Hyperlink>

这篇关于UserControl 的相对源绑定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆