C#/ WPF:获取DataTemplate中元素的绑定路径
如何在DataTemplate中获取元素的绑定路径? 我的XAML看起来像这样:
获取“普通”GridViewColumnHeader.DisplayMemberBinding的绑定路径是
var field = (string)((Binding)((GridViewColumnHeader)e.OriginalSource).Column.DisplayMemberBinding).Path.Path;
如何在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(); } } }
XAML:
第二个策略是打开Snoop或WPF Inspector 。 目标是以编程方式在可视树中搜索感兴趣的TextBlock。 但是,ListView中可能有很多TextBlocks。 实际上,Header可能正在使用一个。 因此,第一步是确定单元格 TextBlock的唯一祖先。 查看可视化树,有两个不错的候选者:ScrollContentPresenter(具有模板部件名称,应该是唯一的)和GridViewRowPresenter。 最好让祖先接近感兴趣的TextBlock。 这降低了其他TextBlocks扭曲搜索结果的可能性。 因此,GridViewRowPresenter是首选。
添加一个或两个实用程序方法以执行可视树搜索。
static public class ControlAux { static public IEnumerable GetVisualDescendants (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 (child)) { yield return descendant; } } } static public T FindVisualDescendant (this DependencyObject item, string descendantName) where T : DependencyObject { return GetVisualDescendants (item).Where( descendant => { var frameworkElement = descendant as FrameworkElement; return frameworkElement != null ? frameworkElement.Name == descendantName : false; }). FirstOrDefault(); } }
现在,通过可视树执行两次搜索,第一次搜索结果充当第二次搜索的根。 从ListView开始,找到GridViewRowPresenter。 从GridViewRowPresenter开始,找到一个TextBlock。 查询其Text绑定并最终访问路径。
GridViewRowPresenter gvrp = lv.GetVisualDescendants().FirstOrDefault(); TextBlock tb = gvrp.GetVisualDescendants().FirstOrDefault(); string path = BindingOperations.GetBinding(tb, TextBlock.TextProperty).Path.Path;
重要的是要注意ListView的ControlTemplates和DataTemplates必须膨胀到它们的实际可视元素中,以便搜索起作用。 如果没有发生通货膨胀,那么这些要素就不存在了。 您可以首先在主窗口的构造函数中尝试搜索,然后在窗口的OnSourceInitialized中尝试搜索。 此外,为简洁起见,省略了所有错误检查。
最后,这第二个策略甚至没有远程防弹。 当使用新的ControlTemplates和DataTemplates时,WPF元素可以具有任意复杂的视觉合成。 但是,这是一个很好的起点,可以考虑如何在任何情况下解决问题。