WPF是否有办法在MouseMove事件上获取鼠标下的元素数组?
这个让我难过.我们有一个自定义ItemsControl,它既使用自定义容器,也使用自定义面板作为ItemsHost.现在,该面板有一些容器需要用于渲染目的的度量标准.由于它们是可视化树中面板的直接子节点,因此您认为容器的Parent属性将返回面板,但它不会!
我已经在标准ListBox上使用Snoop确认了这个确切的事情,所以这不是我们的代码所独有的,但显然是ItemsControls的所有容器.
现在我知道我可以使用VisualTreeHelper来获取可视化父级(这是我需要的),但为什么父级不是面板?
如果参数是面板只是Visual Tree的一部分而Parent是为逻辑树保留的,那么父节点不是ItemsControl吗?
如果容器中的参数也是ItemsControl的可视树而不是逻辑树的一部分,那么为什么容器中托管的内容会将容器作为其Parent属性返回?
这意味着如果您从数据项中走出逻辑树,则停在容器上,这可以解释为什么我们从容器到面板的绑定没有按预期工作.(我相信绑定是基于逻辑层次结构而不是视觉层次结构,但我必须进行测试才能确定.)
有时右键单击treeviewitem结果未处理InvalidOperationException.在后面的代码中,我选择右键单击的行:
static TreeViewItem VisualUpwardSearch(DependencyObject source)
{
while (source != null && !(source is TreeViewItem))
source = VisualTreeHelper.GetParent(source);
return source as TreeViewItem;
}
private void OnPreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
TreeViewItem treeViewItem = VisualUpwardSearch(e.OriginalSource as DependencyObject);
if (treeViewItem != null)
{
treeViewItem.Focus();
e.Handled = true;
}
}
Run Code Online (Sandbox Code Playgroud)
根据stacktrace,上面是问题的根源.
XAML:
<UserControl.Resources>
<HierarchicalDataTemplate ItemsSource="{Binding ClassesItemsSource}" DataType="{x:Type pnls:FavoriteObjectTableViewModel}">
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Converter={StaticResource nameToBitmapSource}}" DataContext="{Binding Bitmap}" />
<Label Content="{Binding TableName}"/>
</StackPanel>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type pnls:FavoriteObjectClassViewModel}">
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Bitmap, Converter={StaticResource UriToCachedImageConverter}}"/>
<Label Content="{Binding …
Run Code Online (Sandbox Code Playgroud) 我有这个静态辅助函数:
public static DependencyObject GetParentObject(DependencyObject child)
{
if (child == null) return null;
ContentElement contentElement = child as ContentElement;
if (contentElement != null)
{
var parent = ContentOperations.GetParent(contentElement);
if (parent != null) return parent;
var fce = contentElement as FrameworkContentElement;
return fce != null ? fce.Parent : null;
}
//if it's not a ContentElement, rely on VisualTreeHelper
return VisualTreeHelper.GetParent(child);
}
Run Code Online (Sandbox Code Playgroud)
它适用于实际应用程序,但我正在尝试为它编写一些单元测试.这是我的第一次尝试:
[Test]
public void GetParentObject_returns_immediate_parent()
{
var contentControl = new ContentControl();
var textBox = new TextBox();
contentControl.BeginInit();
contentControl.Content = textBox; …
Run Code Online (Sandbox Code Playgroud) 我想在WPF Canvas组件上执行rectangual命中测试,以获得与Rectangle框架元素重叠的控件.我找到了一个Silverlight的VisualTreeHelper.FindElementsInHostCoordinates
方法,但显然它在WPF中不可用.
实现此类功能的最佳方法是什么?
我正在使用VisualTreeHelper方法FindElementsInHostCoordinates在给定的X和Y位置查找ListBoxItem.但是,X和Y值似乎与整个页面中的点有关,而不仅仅是我感兴趣的ListBox(即使我将该元素传递给方法的子树参数).下面,这是指从ListBox派生的自定义控件.
foreach (UIElement element in VisualTreeHelper.FindElementsInHostCoordinates(new Point(X, Y), this))
{
if (element is ListBoxItem)
{
int index = this.ItemContainerGenerator.IndexFromContainer(element);
break;
}
}
Run Code Online (Sandbox Code Playgroud)
因此,(0,0)将相对于整个插件的左上角而不是ListBox的左上角.我是否需要在这里(在代码中)进行一些数学工作以将页面坐标转换为ListBox坐标,或者是否有其他方法来执行命中测试以判断给定的X和Y点是否在ListBoxItem上?
谢谢.
好的,我本以为这是一个简单的问题,但是显然这让我感到困惑。
当我尝试设置RibbonComboBox的高度时,它并没有移动它的实际大小,只是围绕它的盒子移动。
这是我的XAML:
<ribbon:RibbonComboBox
DisplayMemberPath="CompanyCode"
Height="22"
Margin="0,0,0,-30"
VerticalAlignment="Bottom"
Width="102">
<ribbon:RibbonGallery SelectedValue="{Binding Path=Companies.SelectedItem,
ValidatesOnDataErrors=true,
NotifyOnValidationError=true }">
<ribbon:RibbonGalleryCategory ItemsSource="{Binding Path=Companies.Items,
NotifyOnValidationError=true,
ValidatesOnDataErrors=true}" />
</ribbon:RibbonGallery>
</ribbon:RibbonComboBox>
Run Code Online (Sandbox Code Playgroud)
我可以将高度更改为200或1,但是高度永远不会改变。
我究竟做错了什么?
谢谢,埃罗克
我有以下C#代码来查找DepedendencyObject的子代:
public static IEnumerable<T> FindVisualChildren<T>(DependencyObject parent) where T : DependencyObject
{
int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < childrenCount; i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
T childType = child as T;
if (childType == null)
{
foreach (var other in FindVisualChildren<T>(child))
yield return other;
}
else
{
yield return (T)child;
}
}
}
Run Code Online (Sandbox Code Playgroud)
当我遍历底部发布的XAML中的TabItems时,将每个TabItem传递给上面的方法,要求它查找所有Expanders,它什么都不返回.此外,我在附加到每个选项卡项的Loaded事件的事件处理程序中发出此请求.
<TextBlock Text="Number of Parts" Grid.Column="0"/>
<ComboBox Grid.Column="2"
Margin="0,0,0,2"
/>
</Grid>
</Expander>
<Expander Header="Date/Time Format"
Margin="5,0,5,0"
Padding="3,3,0,0"
IsExpanded="True" >
<Grid Margin="20,4,0,4">
<Grid.RowDefinitions> …
Run Code Online (Sandbox Code Playgroud) 我正试图在Canvas上测试一堆UserControls.我不希望HitTest()在整个可视树中走路,所以我使用FilterCallback来确保我只测试UserControl.
我的问题是UserControl永远不会命中,它应该,但它不会.如果我使用FilterCallback,我会返回它什么都没有.如果我让HitTest运行可视树,它会跳过UserControl.
这是一些代码:
<Canvas x:Name="Container">
<UserControl>
<Grid>
<Rectangle />
</Grid>
</UserControl>
<UserControl>
<Grid>
<Rectangle />
</Grid>
</UserControl>
</Canvas>
...
VisualTreeHelper.HitTest(Container, OnFilter, OnResult, myPoint);
...
private void OnResult(DependencyObject o)
{
//I'll get the Rectangle here, but never the userControl
}
private void OnFilter(DependencyObject o)
{
//I will get the UserControl here, but even when I do nothing more than continue, it will not trigger a visualHit. But the child rectangle will.
}
Run Code Online (Sandbox Code Playgroud) 似乎在Mouse下检索元素的所有方法都与Visual Hit测试有关.
是否有一些我缺少的机制可以让我抓住实际UIElement
代表HitTest
返回的当前可视树?
我正在做的总结:
我有一个自定义工具提示类,它依赖于基于鼠标结束的UIElement做的事情.
简单地说,它挂钩到拥有Window的PreviewMouseMove
事件并更新"当前项目".此当前项应表示UIElement
鼠标当前位于顶部.
不幸的是,我所遇到的一切Mouse.DirectlyOver
,VisualTreeHelper.HitTest
(包括回调)不起作用.
任何人都可以提供有关如何在Window MouseMove
事件中的WPF中完成看似简单的任务的见解吗?
我将重点放在Popup的开头:
wcl:FocusHelper.IsFocused="{Binding RelativeSource={RelativeSource Self}, Path=IsOpen}"
Run Code Online (Sandbox Code Playgroud)
FocusHelper类代码:
public static class FocusHelper
{
public static readonly DependencyProperty IsFocusedProperty =
DependencyProperty.RegisterAttached("IsFocused", typeof(bool?), typeof(FocusHelper), new FrameworkPropertyMetadata(IsFocusedChanged));
public static bool? GetIsFocused(DependencyObject element)
{
if (element == null)
{
throw new ArgumentNullException("element");
}
return (bool?)element.GetValue(IsFocusedProperty);
}
public static void SetIsFocused(DependencyObject element, bool? value)
{
if (element == null)
throw new ArgumentNullException("element");
element.SetValue(IsFocusedProperty, value);
}
private static void IsFocusedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var fe = (FrameworkElement)d;
if (e.OldValue == null)
{
fe.GotFocus += ElementGotFocus;
fe.LostFocus += …
Run Code Online (Sandbox Code Playgroud) 我UserControl
在另一个中有一个“子项” UserControl
(它充当 a 中的 TabItem TabControl
)。在子项UserControl
和 TabItem 祖先之间是许多其他控件(例如:Grid
s、 a StackPanel
,可能是 aScrollViewer
等)。
UserControl
我想访问我的孩子中TabItem 的属性UserControl
,并自定义一个通常 建议的递归函数,该函数沿着可视化树向上移动。但是,这总是在第一次空检查时返回true
,直到我在逻辑树上添加查询。
代码:
public MyTabItem FindParentTabItem(DependencyObject child)
{
DependencyObject parent = VisualTreeHelper.GetParent(child) ?? LogicalTreeHelper.GetParent(child);
// are we at the top of the tree
if (parent == null)
{
return null;
}
MyTabItem parentTabItem = parent as MyTabItem;
if (parentTabItem != null)
{
return parentTabItem;
}
else
{
//use recursion until …
Run Code Online (Sandbox Code Playgroud) visualtreehelper ×12
wpf ×11
c# ×4
visual-tree ×3
hittest ×2
silverlight ×2
element ×1
ismouseover ×1
itemscontrol ×1
mouse ×1
parent ×1
popup ×1
ribbon ×1
tabcontrol ×1
unit-testing ×1
xaml ×1