我需要将某些东西绑定到我的VisualTree中的元素的子元素。
用户控件中的:
<StackPanel>
<DataGrid x:Name="dataGrid" />
<Control Tag="{Binding ElementName=dataGrid}" />
</StackPanel>
在DataGrid的模板中:
<Template TargetType=DataGrid>
......
<Control x:Name="FindMe" />
......
</Template>
我想做的是遍历DataGrid的VisualTree,为此目的,我创建了一个 自定义标记扩展名:
public class TemplatePartBinding : MarkupExtension
{
public override object ProvideValue(IServiceProvider serviceProvider)
{
Binding binding = new Binding();
binding.ElementName = ElementName;
// HOW DO I GET THE SOURCE OBJECT FROM THE BINDING ?
DataGrid dataGrid = // Extract the DataGrid from the binding.
Control _findMe = VisualTreeHelperExtentions.FindVisualChild<Control>(dataGrid,"FindMe");
binding.Target = _findMe;
binding.Path = new PropertyPath("Tag");
return binding;
}
[ConstructorArgument("ElementName")]
public string ElementName
{
get;
set;
}
[ConstructorArgument("TemplatePartName")]
public string TemplatePartName
{
get;
set;
}
}
这里在ProvideValue中,在给出绑定的ElementName值后,我不想找到DataGrid(绑定的源对象),
如何从刚刚创建的绑定中提取DependencyObject(My DataGrid)?
答案 0 :(得分:2)
您可以在标记扩展中提供DataGrid
实例提供值方法但 FindMe Control
您将无法使用VisualTree扩展方法因为当调用此方法时, 当时不会创建用于dataGrid的Visual Tree 。
另外,逻辑树也没有任何帮助,因为Control是Visual child而不是dataGrid的逻辑子。
但是,对于查找dataGrid的问题,您可以这样:
public override object ProvideValue(IServiceProvider serviceProvider)
{
IRootObjectProvider provider = (IRootObjectProvider)serviceProvider
.GetService(typeof(IRootObjectProvider));
DataGrid dataGrid =
LogicalTreeHelper.FindLogicalNode((DependencyObject)provider.RootObject,
ElementName) as DataGrid;
....
}
IRootObjectProvider
会得到RootObject which will be UserControl
并最终通过遍历LogicalTree而不是VisualTree来获取DataGrid,因为它将返回null。 (Visual Tree尚未创建)。