Silverlight:FrameworkElement.FindName()在浏览器窗口中未“可见”时无法找到控件

4
我遇到了一个问题,我正在使用FrameworkElement对象的"FindName()"方法来搜索元素的子控件。但是我发现了一些有趣的行为,却无法解决。如果用户滚动浏览器窗口,使得控件本身在窗口框架的上下文中不再可见,那么"FindName()"将无法返回该元素。然而,如果该控件在窗口框架内可见,则可以正常找到它。
这是否是一个已知的问题?还有其他人遇到过这种情况吗?
我并不是在谈论控件的Visibility属性。Visibility属性已设置为Visible。
更新: 我尝试在ListBox控件(我要搜索的容器)上设置VirtualizingStackPanel.VirtualizationMode="Standard",但仍然无法找到指定的控件。

1
你的命名控件是否位于虚拟化容器中? - Denis
包含我正在寻找的控件的控件是一个ListBox。我相信我刚刚发现ListBoxes默认情况下启用了UI虚拟化,这很可能是问题所在。我如何为特定的控件关闭UI虚拟化?尝试在ListBox控件本身上使用VirtualizingStackPanel.VirtualizationMode="Standard"。稍后会有报告。 - ghost_mv
2个回答

3
如果我理解正确的话,您是说当控件滚动出应用程序的视口时,即使其可见属性仍为true,FrameworkElement.FindName("")也无法找到它。
我假设您已经掌握了有关Xaml作用域的所有基础知识等。如果您正在动态添加控件,您确定您正在从正确的父元素等遍历吗?如果是这样:
使用RedGate的反射器,我们可以看到FrameWorkElement.FindName的实现如下:
public object FindName(string name)
{
    return XcpImports.DependencyObject_FindName(this, name);
}

XcpImports.DependencyObject_FindName被实现为:
[SecuritySafeCritical]
internal static DependencyObject DependencyObject_FindName(DependencyObject referenceDO, string name)
{
    int num;
    IntPtr ptr;
    CheckThread();
    if (name == null)
    {
        throw new ArgumentNullException("name");
    }
    uint hr = FindNameNative(JoltHelper.Context, (uint) name.Length, name, referenceDO.NativeObject, out num, out ptr);
    GC.KeepAlive(referenceDO);
    if ((hr != 0) && (hr != 0x80004005))
    {
        throw Error.MarshalXresultAsException(hr);
    }
    return (DependencyObject) ConvertDO(ptr, num, true);
}

因此,除非你遇到异常情况,否则我认为最有趣的一行代码可能是:

uint hr = FindNameNative(JoltHelper.Context, (uint) name.Length, name, referenceDO.NativeObject, out num, out ptr);

这是通过进入本地代码并在XcpImports中定义导入dll实现的:

[DllImport("agcore", EntryPoint="FindName", CharSet=CharSet.Unicode)]
private static extern uint FindNameNative(IntPtr context, uint cString, [MarshalAs(UnmanagedType.LPWStr)] string name, IntPtr referenceObject, out int typeIndex, out IntPtr obj);

不要与Developer Express的AgCore混淆。
这是Ed Burnette在ZdNet上发表的文章(约2007年)。

http://www.zdnet.com/blog/burnette/dissecting-silverlight/297

说的是:

agcore.dll(已安装2.2M)- 这是核心ActiveX控件,负责Silverlight的渲染和事件,包括音频和视频解码。

它还在下面说:

npctrl.dll(460K)- agcore.dll的包装器,使其在Firefox内运行。

所以我的第一个问题是:您的问题在每个浏览器中都一致吗?也许是某个浏览器/版本中的agcore.dll包装器有问题,而不是核心技术(agcore.dll)本身。

我正在IE中进行测试。在Chrome中也是一样的。没有任何异常被抛出,它只是找不到控件。 - ghost_mv
好的,那么在这种情况下,我会改变策略并三重检查问题,例如重新定义范围等。这可能是一个“真正”的错误,但如果它直到游戏的后期才被发现,我会感到惊讶。尝试使用此文章中提供的方法来检查您的可视树,并特别使用提到的Wpf Snoop工具(希望它可以捕获Silverlight应用程序,如果不能,请尝试离线)在接受的答案中。https://dev59.com/snRB5IYBdhLWcg3wZmdz - rism
我会回到绘图板上重新思考,但再次强调,在“FindName()”调用之前的断点处逐步执行代码,并且由于控件滚动出视图而进行的简单控制更改,导致无法找到该控件。 - ghost_mv

2

确实是 UI 虚拟化引起的问题。感谢。 - ghost_mv

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接