如何在ComboBox模板中获取Popup的宽度

时间:2015-01-20 14:27:23

标签: c# wpf

我有这个IMultiValueConverter,我想在列出更改值时找出ComboBox的宽度。

我看过MSDN ComboBox模板,可以看到有一个Popup,x:Name =" Popup",实际上它在页面顶部有点令人困惑叫它PART_Popup。 MSDN link

如何获取Popup对象以确定其宽度?如果弹出窗口不是出于任何原因的选项,那么它内部的网格呢。

我已经看到其他人之前已经遍历所有寻找文本渲染中最大长度的项目,如果可能的话,我想尝试这种方式。

public class ComboBoxWidthConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        double cbxWidth = 100;

        if (values[0] == null || values[1] == null)
            return cbxWidth;

        ComboBox cb = (ComboBox)values[0];

        int itemCount = (int)values[1];

        if (itemCount == 0)
            return cbxWidth;

        //Find popup and retrieve width.

        return cbxWidth;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

1 个答案:

答案 0 :(得分:0)

这很有效:您可能会想到一种将它集成到Converter中的方法。

  void MainWindow_Loaded(object sender, RoutedEventArgs e)
  {
       // comboBox is an element in 'MainWindow'
       var popup = VisualTreeHelperExtensions.FindVisualChild<Popup>(comboBox);
  }

  public static T FindVisualChild<T>(DependencyObject depObj) where T : Visual
    {
        if (depObj != null && IsVisual(depObj))
        {
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
            {
                DependencyObject child = VisualTreeHelper.GetChild(depObj, i);

                if (child != null && child is T)
                {
                    return (T)child;
                }

                foreach (T childOfChild in FindVisualChildren<T>(child))
                {
                    return childOfChild;
                }
            }
        }
        return null;
    }    

    public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
    {
        if (depObj == null)
            yield break;

        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
        {
            if (IsVisual(depObj))
            {
                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 static bool IsVisual(DependencyObject depObj)
    {
        return depObj is Visual || depObj is Visual3D;
    }