Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/281.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么VisualTreeHelper.GetChildrenCount()返回0作为弹出窗口?_C#_Wpf_Popup_Visualtreehelper_Visual Tree - Fatal编程技术网

C# 为什么VisualTreeHelper.GetChildrenCount()返回0作为弹出窗口?

C# 为什么VisualTreeHelper.GetChildrenCount()返回0作为弹出窗口?,c#,wpf,popup,visualtreehelper,visual-tree,C#,Wpf,Popup,Visualtreehelper,Visual Tree,我在弹出窗口打开时将焦点移到弹出窗口: wcl:FocusHelper.IsFocused="{Binding RelativeSource={RelativeSource Self}, Path=IsOpen}" FocusHelper类别代码: public static class FocusHelper { public static readonly DependencyProperty IsFocusedProperty = DependencyP

我在弹出窗口打开时将焦点移到弹出窗口:

wcl:FocusHelper.IsFocused="{Binding RelativeSource={RelativeSource Self}, Path=IsOpen}"
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 += ElementLostFocus;
                fe.IsVisibleChanged += ElementIsVisibleChanged;
            }

            if (e.NewValue == null)
            {
                fe.GotFocus -= ElementGotFocus;
                fe.LostFocus -= ElementLostFocus;
                fe.IsVisibleChanged -= ElementIsVisibleChanged;
                return;
            }

            if ((bool)e.NewValue)
            {
                fe.SetFocusWithin();
            }
        }

        private static void ElementIsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            var fe = (FrameworkElement)sender;

            if (fe.IsVisible 
                && (bool)(((FrameworkElement) sender).GetValue(IsFocusedProperty))) // Bring focus to just become visible element.
                fe.Focus();
        }

        private static void ElementGotFocus(object sender, RoutedEventArgs e)
        {
            ((FrameworkElement)sender).SetCurrentValue(IsFocusedProperty, true);
        }

        private static void ElementLostFocus(object sender, RoutedEventArgs e)
        {
            ((FrameworkElement)sender).SetCurrentValue(IsFocusedProperty, false);
        }

        /// <summary>
        /// Tries to set focus to the element or any other element inside this one.
        /// Tab index is respected
        /// </summary>
        /// <param name="element"></param>
        /// <returns></returns>
        public static bool SetFocusWithin(this DependencyObject element)
        {
            if (element == null)
                throw new ArgumentNullException("element");

            var inputElement = element as IInputElement;
            if (inputElement == null || !inputElement.Focus())
            {
                var children = element.GetVisualChildrenSortedByTabIndex().Where(child => !(child is Control) || (bool)child.GetValue(Control.IsTabStopProperty) );
                return children.Any(SetFocusWithin);
            }

            return true;
        }
    }
公共静态类FocusHelper
{
公共静态只读从属属性IsFocusedProperty=
DependencyProperty.RegisterAttached(“IsFocused”、typeof(bool?)、typeof(FocusHelper)、新框架属性元数据(IsFocusedChanged));
公共静态bool?GetIsFocused(DependencyObject元素)
{
if(元素==null)
{
抛出新的ArgumentNullException(“元素”);
}
return(bool?)元素.GetValue(IsFocusedProperty);
}
公共静态void SetIsFocused(DependencyObject元素,bool?值)
{
if(元素==null)
抛出新的ArgumentNullException(“元素”);
元素设置值(IsFocusedProperty,value);
}
私有静态void的焦点已更改(DependencyObject d、DependencyPropertyChangedEventArgs e)
{
var fe=(框架元素)d;
如果(e.OldValue==null)
{
fe.GotFocus+=元素GotFocus;
fe.LostFocus+=元素LostFocus;
fe.IsVisibleChanged+=元素IsVisibleChanged;
}
如果(e.NewValue==null)
{
fe.GotFocus-=元素GotFocus;
fe.LostFocus-=元素LostFocus;
fe.IsVisibleChanged-=元素IsVisibleChanged;
返回;
}
if((bool)e.NewValue)
{
fe.SetFocusWithin();
}
}
私有静态void元素IsVisibleChanged(对象发送方,DependencyPropertyChangedEventArgs e)
{
var fe=(FrameworkElement)发送方;
如果(fe)是可见的
&&(bool)(((FrameworkElement)sender.GetValue(IsFocusedProperty))//使焦点刚好成为可见元素。
fe.Focus();
}
私有静态void元素GotFocus(对象发送方,RoutedEventArgs e)
{
((FrameworkElement)sender).SetCurrentValue(IsFocusedProperty,true);
}
私有静态void元素LostFocus(对象发送方,RoutedEventTarget e)
{
((FrameworkElement)sender).SetCurrentValue(IsFocusedProperty,false);
}
/// 
///尝试将焦点设置为元素或此元素内的任何其他元素。
///标签索引是受尊重的
/// 
/// 
/// 
公共静态bool SetFocusWithin(此DependencyObject元素)
{
if(元素==null)
抛出新的ArgumentNullException(“元素”);
var inputElement=作为IIInputElement的元素;
if(inputElement==null | |!inputElement.Focus())
{
var children=element.GetVisualChildrenSortedByTabIndex()。其中(child=>!(child是控件)| |(bool)child.GetValue(Control.IsTabStopProperty));
返回children.Any(SetFocusWithin);
}
返回true;
}
}
ElementTreeHelper类零件:

public static IEnumerable<DependencyObject> GetVisualChildren(this DependencyObject parent)
        {
            if (parent == null)
                throw new ArgumentNullException("parent");

            var count = VisualTreeHelper.GetChildrenCount(parent);
            for (var i = 0; i < count; i++)
                yield return VisualTreeHelper.GetChild(parent, i);
        }

        public static IEnumerable<DependencyObject> GetVisualChildrenSortedByTabIndex(this DependencyObject parent)
        {
            if (parent == null)
                throw new ArgumentNullException("parent");

            return parent.GetVisualChildren().OrderBy(KeyboardNavigation.GetTabIndex);
        }
公共静态IEnumerable GetVisualChildren(此DependencyObject父对象)
{
如果(父项==null)
抛出新的ArgumentNullException(“父级”);
变量计数=VisualTreeHelper.GetChildrenCount(父级);
对于(变量i=0;i
问题是 当父项弹出时,var count=VisualTreeHelper.GetChildrenCount(父项)==0

更新


答案是弹出窗口本身不包含子对象。相反,它创建了一个PopuRoot(内部类),它是一个新HWND的根可视对象,该HWND创建用于在一个单独的顶级窗口(或xbap中的子窗口)中托管弹出窗口的内容。弹出窗口的子窗口托管在该弹出窗口中的AdornedDecorator中。

我参加聚会有点晚,但AndrewS的回答帮助我放弃在弹出窗口中使用GetChildrenCount。我注意到Popup的Child属性被正确填充,所以我创建了一个单独的代码路径来查找Popup对象的特定子类型。下面是我用来按类型(也可以按名称)查找特定子级的代码:

public static TChildItem FindVisualChild(此DependencyObject DependencyObject,字符串名称),其中TChildItem:DependencyObject
{
//先搜索直系子女(广度优先)
var childrenCount=VisualTreeHelper.GetChildrenCount(dependencyObject);
//http://stackoverflow.com/questions/12304904/why-visualtreehelper-getchildrencount-returns-0-for-popup
如果(childrenCount==0&&dependencyObject弹出)
{
var popup=作为弹出窗口的dependencyObject;
返回popup.Child!=null?popup.Child.FindVisualChild(名称):null;
}
对于(变量i=0;i
public static TChildItem FindVisualChild<TChildItem>(this DependencyObject dependencyObject, String name) where TChildItem : DependencyObject
{
  // Search immediate children first (breadth-first)
  var childrenCount = VisualTreeHelper.GetChildrenCount(dependencyObject);

  //http://stackoverflow.com/questions/12304904/why-visualtreehelper-getchildrencount-returns-0-for-popup
  if (childrenCount == 0 && dependencyObject is Popup)
  {
    var popup = dependencyObject as Popup;
    return popup.Child != null ? popup.Child.FindVisualChild<TChildItem>(name) : null;
  }

  for (var i = 0; i < childrenCount; i++)
  {
    var child = VisualTreeHelper.GetChild(dependencyObject, i);
    var nameOfChild = child.GetValue(FrameworkElement.NameProperty) as String;

    if (child is TChildItem && (name == String.Empty || name == nameOfChild))
      return (TChildItem)child;
    var childOfChild = child.FindVisualChild<TChildItem>(name);
    if (childOfChild != null)
      return childOfChild;
  }
  return null;
}

public static TChildItem FindVisualChild<TChildItem>(this DependencyObject dependencyObject) where TChildItem : DependencyObject
{
  return dependencyObject.FindVisualChild<TChildItem>(String.Empty);
}