C#/WPF:获取数据模板中元素的绑定路径
如何获取DataTemplate中元素的绑定路径? 我的XAML如下所示:C#/WPF:获取数据模板中元素的绑定路径,c#,wpf,binding,datatemplate,C#,Wpf,Binding,Datatemplate,如何获取DataTemplate中元素的绑定路径? 我的XAML如下所示: <GridViewColumn Header="Double"> <GridViewColumn.CellTemplate> <DataTemplate> <TextBlock Text="{Binding TotalValues, Mode=OneWay, StringFormat=\{0:0\'0.00\}, Converter
<GridViewColumn Header="Double">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding TotalValues, Mode=OneWay, StringFormat=\{0:0\'0.00\}, Converter={StaticResource GridValueConverter}}" TextAlignment="Right" Width="auto"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Comments" DisplayMemberBinding="{Binding Path=Comments, Mode=OneWay}" Width="auto"/>
如何为
TextBlock.Text的绑定路径获得相同的值?这是一个很好的问题。代码和XAML之间有一个分离,而且,就代码而言,从哪里开始寻找并不明显。此外,DataTemplate被编译成BAML,因此在运行时不易访问
找到绑定路径至少有两种策略
第一个策略是将路径保存为某个静态变量
代码隐藏:
namespace TempProj
{
using System.Windows;
public partial class MainWindow : Window
{
static public readonly PropertyPath BindingPath = new PropertyPath("X");
public MainWindow()
{
InitializeComponent();
}
}
}
<Window x:Class="TempProj.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TempProj"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Vector3DCollection x:Key="Coordinates">
<Vector3D X="1" Y="0" Z="0"/>
<Vector3D X="0" Y="22" Z="0"/>
<Vector3D X="0" Y="0" Z="333"/>
<Vector3D X="0" Y="4444" Z="0"/>
<Vector3D X="55555" Y="0" Z="0"/>
</Vector3DCollection>
</Window.Resources>
<ListView x:Name="lv" ItemsSource="{StaticResource Coordinates}">
<ListView.View>
<GridView>
<GridViewColumn Header="{x:Static local:MainWindow.BindingPath}">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path={x:Static local:MainWindow.BindingPath}}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
</Window>
XAML:
namespace TempProj
{
using System.Windows;
public partial class MainWindow : Window
{
static public readonly PropertyPath BindingPath = new PropertyPath("X");
public MainWindow()
{
InitializeComponent();
}
}
}
<Window x:Class="TempProj.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TempProj"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Vector3DCollection x:Key="Coordinates">
<Vector3D X="1" Y="0" Z="0"/>
<Vector3D X="0" Y="22" Z="0"/>
<Vector3D X="0" Y="0" Z="333"/>
<Vector3D X="0" Y="4444" Z="0"/>
<Vector3D X="55555" Y="0" Z="0"/>
</Vector3DCollection>
</Window.Resources>
<ListView x:Name="lv" ItemsSource="{StaticResource Coordinates}">
<ListView.View>
<GridView>
<GridViewColumn Header="{x:Static local:MainWindow.BindingPath}">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path={x:Static local:MainWindow.BindingPath}}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
</Window>
第二个策略是开放或开放。目标是以编程方式在可视化树中搜索感兴趣的文本块。但是,ListView中可能有许多文本块。事实上,标题可能正在使用一个。因此,第一步是识别细胞文本块的唯一祖先。查看可视化树,有两个合适的候选对象:ScrollContentPresenter(具有模板部分名称,应该是唯一的)和GridViewRowPresenter。祖先最好靠近感兴趣的文本块。这降低了其他文本块扭曲搜索结果的可能性。因此,GridViewRowPresenter更可取
添加一个或两个实用程序方法来执行可视化树搜索
static public class ControlAux
{
static public IEnumerable<T> GetVisualDescendants<T>(this DependencyObject item) where T : DependencyObject
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(item); ++i)
{
DependencyObject child = VisualTreeHelper.GetChild(item, i);
if (typeof(T) == (child.GetType()))
{
yield return (T)child;
}
foreach (T descendant in GetVisualDescendants<T>(child))
{
yield return descendant;
}
}
}
static public T FindVisualDescendant<T>(this DependencyObject item, string descendantName) where T : DependencyObject
{
return
GetVisualDescendants<T>(item).Where(
descendant =>
{
var frameworkElement = descendant as FrameworkElement;
return frameworkElement != null ? frameworkElement.Name == descendantName : false;
}).
FirstOrDefault();
}
}
静态公共类ControlAux
{
静态公共IEnumerable GetVisualDescendants(此DependencyObject项),其中T:DependencyObject
{
for(int i=0;i
{
var frameworkElement=作为frameworkElement的后代;
return frameworkElement!=null?frameworkElement.Name==后代名称:false;
}).
FirstOrDefault();
}
}
现在,通过可视化树执行两个搜索,第一个搜索结果作为第二个搜索的根。从ListView开始,可以找到GridViewRowPresenter。从GridViewRowPresenter开始,会找到一个文本块。查询其文本绑定并最终访问路径
GridViewRowPresenter gvrp = lv.GetVisualDescendants<GridViewRowPresenter>().FirstOrDefault();
TextBlock tb = gvrp.GetVisualDescendants<TextBlock>().FirstOrDefault();
string path = BindingOperations.GetBinding(tb, TextBlock.TextProperty).Path.Path;
GridViewRowPresenter gvrp=lv.getVisualDescendats().FirstOrDefault();
TextBlock tb=gvrp.getVisualDescendats().FirstOrDefault();
字符串路径=BindingOperations.GetBinding(tb,TextBlock.TextProperty).path.path;
需要注意的是,ListView的ControlTemplates和DataTemplates必须膨胀到它们的实际可视元素中,才能进行搜索。如果通货膨胀没有发生,这些因素就不存在了。您可以先在主窗口的构造函数中尝试搜索,然后在窗口的OnSourceInitialized中尝试搜索来测试这一点。此外,为了简洁起见,所有错误检查都被省略了
最后,第二种策略甚至一点也不防弹。当使用新的ControlTemplates和DataTemplates时,WPF元素可以具有任意复杂的可视组合。然而,这是一个很好的起点,可以让你思考在任何情况下如何解决问题。@Andrew Van Berg OMG!非常感谢。Snoop和WPF Inspector是有史以来最好的东西@亚历山大·范伯格-谢谢你,先生