WPF,与TemplatedParent绑定时的有趣事项

3

控件模板:

    <ControlTemplate x:Key="BasicShape2">
    <StackPanel Name="sp">
        <Border Name="bd" CornerRadius="3.5" BorderThickness="1" BorderBrush="{Binding RelativeSource={RelativeSource TemplatedParent},Path=DataContext.NodeType, Converter={StaticResource NodeTypeColorConverter}, Mode=OneWay}" Height="32" Padding="1">
            <TextBlock Name="tbName" Grid.Column="1" Text="" HorizontalAlignment="Center" VerticalAlignment="Bottom" FontSize="16" />
        </Border>
    </StackPanel>
</ControlTemplate>

这个模板所适用的类:

    public class MyThumbEx : Thumb
{
    public static readonly DependencyProperty MemberInfoProperty = DependencyProperty.Register("MemberInfo", typeof(FamilyMemberInfo), typeof(MyThumbEx));
    public FamilyMemberInfo MemberInfo
    {
        get { return (FamilyMemberInfo)GetValue(MemberInfoProperty); }
        set { SetValue(MemberInfoProperty, value); }
    }

    public MyThumbEx(ControlTemplate template, FamilyMemberInfo info, Point position)
    {
        this.MemberInfo = info;
        this.DataContext = this.MemberInfo;
        this.Template = template;
    }

    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();
        this.ApplyTextContent();
    }

    public void ApplyTextContent()
    {
        TextBlock tbName = this.Template.FindName("tbName", this) as TextBlock;
        if (tbName != null)
        {
            tbName.Text = this.MemberInfo.Name;
        }
    }
}

初始化并在画布上显示:

        public MainWindow()
    {
        InitializeComponent();
        //
        FamilyMemberInfo mi = new FamilyMemberInfo();
        mi.Name = "someone";
        mi.ID = "id1";
        MyThumbEx te = new MyThumbEx(Application.Current.Resources["BasicShape2"] as ControlTemplate, mi, new Point(0, 0));
        //
        this.cvMain.Children.Add(te);
    }

这些代码可以正常工作,但请注意,在控件模板中,我必须设置Path=DataContext.NodeType,而不仅仅是Path=NodeType。我是WPF的新手,我发现通常情况下,当我没有使用这个模板时进行绑定时,我不需要指定谓词“DataContext”,对吗?为什么我们需要在这里使用它?
另一件我发现的事情是,我可以注释掉this.DataContext = this.MemberInfo,并将绑定路径更改为Path=MemberInfo.NodeType,代码仍然可以正常工作。有人可以为我解释一下吗?
提前致谢!
1个回答

3
如果您不手动更改DataContext,每个子元素都会自动具有其父元素的DataContext。因此,如果您的窗口具有ViewModel作为DataContext,那么所有控件都可以通过{Binding Path=Property}访问ViewModel的属性。
但是,在ControlTemplate的情况下,通常的DataContext从父级到子级的级联流程不适用于此处。因此,您首先必须设置DataContext,可以通过Property="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=DataContext.Property}"或者DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=DataContext}" Property="{Binding Path=Property}"来实现。
至于第二点:可能ControlTemplate自动使用其包含元素的代码后台作为DataContext,因此您可以在不设置DataContext的情况下使用代码后台的属性,但我不能100%确定这一点。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接