c# - UserControl 的 RelativeSource 绑定(bind)

标签 c# wpf user-controls

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

UserControl 的标记如下:

<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 中,如下所示:

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 与命令绑定(bind)一起使用,我必须执行以下操作:

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

如果我改用 Button,则不必提供 RelativeSource。有没有机会我也不必为自定义创建的 UserControl 的绑定(bind)属性提供 RelativeSource

最佳答案

当你写作时

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

WPF 尝试建立到 UserControl 的 DataContext 中的 ViewCustomersCommand 属性的数据绑定(bind),该属性通常继承自控件的父级,并持有对某个 View 模型对象的引用。这在这里不起作用,因为您已将 DataContext 显式设置为 UserControl 实例。

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

所以删除

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

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

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

关于c# - UserControl 的 RelativeSource 绑定(bind),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29075720/

相关文章:

asp.net-mvc - 检查用户是否在用户控件中登录 Asp.net MVC

html - 前端 Rails 应用程序中的代码重用

c# - 为什么我在保存数据库条目时得到 "unhandled exception"?

c# - 用于移动设备上的电话簿的最佳数据结构是什么

wpf - 在 PlacementTarget 的中心和底部对齐的弹出窗口

c# - 使用 taglib 在 WPF 中的图像框中显示封面

c# - 将字符串转换为列表

C#:隐式 Arraylist 赋值是否可能?

c# - 是否有Visual Studio之类的代码编辑器控件?

c# - 将事件处理程序传递给 UserControl 以分配给动态 LinkBut​​ton