控制模板:
<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,代码仍然正常。有人可以为我解释一下吗?
提前致谢!
答案 0 :(得分:3)
如果您不更改DataContext manuelly,则每个子节点都自动拥有其Parent的DataContext。所以如果你的窗口有f.e. ViewModel作为DataContext,其所有控件都可以通过{Binding Path=Property}
访问ViewModels属性。
但是在ControlTemplate的情况下,DataContext从父级到子级的典型流程通常不适用于此处。因此,您必须先通过Property="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=DataContext.Property}"
或DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=DataContext}" Property="{Binding Path=Property}"
设置DataContext。
第二点:可能是,ControlTemplate会自动使用其包含Element作为DataContext的代码隐藏,因此您可以在不设置DataContext的情况下使用代码隐藏属性,但我并非100%确定此