为什么TextBlock不是路由事件上的OriginalSource?我正在显示ListView元素的上下文菜单。上下文菜单附加到ListView的TextBlock,如下所示。上下文菜单正确显示,并且RoutedUIEvent也被触发。问题是在Executed回调中,ExecutedRoutedEventArgs.OriginalSource是ListViewItem而不是TextBlock。我尝试设置IsHitTestVisible属性以及背景(见下文),因为MSDN说OriginalSource是由命中测试确定的。请注意,我在ListView中使用GridView作为视图。这就是为什么我想使用System.Diagnostics获取TextBlock(获取列索引)MainWindowMainWindow.xaml.cs;使用System.Windows;使用System.Windows.Input;namespaceWpfApp1{publicclassData{publicstringMember1{get;放;}}publicpartialclassMainWindow:Window{publicstaticRoutedCommandTest=newRoutedCommand();publicMainWindow(){InitializeComponent();CommandBindings.Add(newCommandBinding(Test,(s,e)=>{Debugger.Break();}));关于你的问题,或者更确切地说......关于WPF的一件令人沮丧的事情,因为它与你的问题中提出的场景有关,WPF似乎很难为这个特定场景设计构建解决方案。特别是:DisplayMemberBinding和CellTemplate属性不能一起使用。即您可以指定一个或另一个,但不能同时指定两者。如果指定了DisplayMemberBinding,则它优先并且不提供显示格式的自定义,除了在隐式使用的TextBlock的样式中应用设置器。DisplayMemberBinding不参与WPF中其他地方常见的隐式数据模板行为。也就是说,当您使用此属性时,控件显式使用TextBlock来显示数据,将值绑定到TextBlock.Text属性。所以你最好绑定到一个字符串值;如果您尝试使用其他类型,WPF不会为您查找任何其他数据模板。然而,即使有这些挫折,我还是可以找到两条不同的途径来解决你的问题。一条路径直接关注您的确切请求,而另一条路径(我希望)退后一步,关注您试图解决的更广泛的问题。第二条路径导致代码比第一条路径更简单并且恕我直言更好的原因还在于它不涉及摆弄可视化树以及该树的各种元素相对于彼此的实现细节。因此,我将从展示开始(即在复杂的意义上,这实际上是“第一”路径,而不是“第二”路径:))。首先,您需要一个小助手类:classGridColumnDisplayData{publicobjectDisplayValue{get;放;}公共字符串ColumnProperty{得到;放;然后,您需要一个转换器来为您的网格单元格生成该类示例:classGridColumnDisplayDataConverter:IValueConverter{publicobjectConvert(objectvalue,TypetargetType,objectparameter,CultureInfoculture){returnnewGridColumnDisplayData{DisplayValue=value,ColumnProperty=(string)parameter};}publicobjectConvert,TypevalueBack(targetType,objectparameter,CultureInfoculture){thrownewNotImplementedException();XAML看起来像这样:它所做的是将数据对象映射到它们各自的属性值,以及这些属性值的名称。这样,当应用数据模板时,MenuItem可以将CommandParameter绑定到该属性值名称,因此可以在处理程序中访问它。请注意,这不是使用DisplayMemberBinding,而是使用CellTemplate并将显示成员绑定移动到模板中的ContentPresenter的内容。由于上述烦恼,这是必需的;否则,无法将用户定义的数据模板应用于用户定义的GridColumnDisplayData对象以正确显示其DisplayValue属性。这里有一些冗余,因为您必须绑定到属性路径并将属性名称指定为转换器参数。不幸的是,后者容易出现印刷错误,因为在编译或运行时无法解决不匹配问题。我认为在调试构建中,您可以添加一些反射以通过转换器参数中给定的属性名称检索属性值,并确保它与绑定路径中给定的相同。在您的问题和评论中,您已经声明您想要回到树上以更直接地找到属性名称。即在命令参数中,传递TextBlock对象引用,然后使用它导航回绑定的属性名称。从直接进入属性名称绑定的意义上说,这更可靠。另一方面,在我看来,取决于可视化树的确切结构和内部发现的绑定更脆弱。从长远来看,这似乎可能会导致更高的维护成本。也就是说,我确实想出了一种方法来实现这一点。首先,与另一个示例一样,您需要一个辅助类来存储数据:publicclassGridCellHelper{publicobjectDisplayValue{get;放;}公共UIElementUIElement{得到;放;}}类似地,转换器(这次是IMultiValueConverter)为每个单元格创建此类的一个实例:=值[0],UIElement=(UIElement)值[1]};}publicobject[]ConvertBack(objectvalue,Type[]targetTypes,objectparameter,CultureInfoculture){thrownewNotImplementedException();最后,XAML:在这个版本中,您可以看到单元格模板用于设置DataContext值,其中包含绑定的属性值和对TextBlock的引用。这些值然后由模板中的各个元素解包,即TextBlock.Text属性和MenuItem.CommandParameter属性。这里明显的缺点是,因为显示成员必须绑定在声明的单元格模板中,所以必须为每一列重复代码。我没有看到重用模板的方法,以某种方式将属性名称传递给它。(另一个版本有类似的问题,但它有一个更简单的实现,所以复制/粘贴看起来并不那么乏味)。但它确实将TextBlock引用发送到您的命令处理程序,这正是您所要求的。就是那个。?以上是C#学习教程:为什么TextBlock不是RoutedEvent上的OriginalSource?如果所有分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
