我使用的是Kinect.Toolbox鼠标和磁控。它在单个页面中完美运行。但是,当我有不同的页面,我在它们之间导航时,我收到一个错误:InvalidOperationException用户代码中的未触发 - 指定的视觉效果不是此视觉中的祖先。这发生在MouseController.cs第158行:
var position = element.TransformToAncestor(rootVisual).Transform(new Point(0, 0));
通过一些调试我明白上一页的磁控制器仍然在列表中并导致问题。所以我尝试清除它们,然后通过以下方式导航到下一页:
MouseController.Current.MagneticsControl.Clear();
然而,我仍然得到同样的错误。如果我在导航之前清除列表我得到错误,因为我仍然在同一页面,磁控制列表变空,如果我在导航后清除它我没有得到错误但我的磁控制器自从没有得到识别他们从名单中清除。有人有解决方案吗?清除此列表的正确位置在哪里?
这是我有磁控制的XAML:
<Grid>
<Button Content="1" local:MagneticPropertyHolder.IsMagnetic="True" Click="Button_Click"/>
</Grid>
在Button_Click上我导航到另一个也有一些磁控制的页面:
private void Button_Click(object sender, RoutedEventArgs e)
{
MouseController.Current.MagneticsControl.Clear();
keyboard pageKeyboard = new keyboard();
NavigationService navigationService = NavigationService.GetNavigationService(this);
navigationService.Navigate(pageKeyboard);
}
答案 0 :(得分:0)
好吧,我这样解决了我的问题:我明白这个问题是因为在可视树仍在组装时调用转换器引起的,因此你的Visual还不是Window的后代。有一些解决方案,比如在您的可视树已经构建完成后进行转换。这是通过使用Dispatcher.BeginInvoke(DispatcherPriority.Render,...)注册Dispatcher回调并在回调中完成工作来完成的。
由于我不想深入了解源代码,而且我还不够用WPF做高级复杂的东西,我使用了自己的解决方案,这可能不是最好的解决方案。而不是清除磁控制列表,我决定以编程方式设置我的磁控制,而不是在XAML中设置它们。通过这种方式,我可以确保在已经构建可视树时设置磁控制器。因此,在Page_Loaded事件中,我设置磁控制器并将它们推入磁控制列表(不确定是否需要最后一部分):
private void Page_Loaded(object sender, RoutedEventArgs e)
{
foreach (Button btn in MagneticButtons)
{
btn.SetValue(MagneticPropertyHolder.IsMagneticProperty, true);
MouseController.Current.MagneticsControl.Add(btn);
}
}
由于我唯一的磁性控件是按钮,您还可以设置其他控件。当我从页面导航到另一个页面时,我取消设置所有磁性按钮并将其从磁控制列表中删除:
foreach (Button btn in MagneticButtons)
{
btn.SetValue(MagneticPropertyHolder.IsMagneticProperty, false);
MouseController.Current.MagneticsControl.Remove(btn);
}
要获取窗口或页面中的控件,您可以使用:
public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
{
if (depObj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
if (child != null && child is T)
{
yield return (T)child;
}
foreach (T childOfChild in FindVisualChildren<T>(child))
{
yield return childOfChild;
}
}
}
}
在我的例子中,例如获取按钮:
private IEnumerable<Button> MagneticButtons = FindVisualChildren<Button>(this);