В WPF, как отобразить AdornerLayer поверх DataGrid - PullRequest
4 голосов
/ 08 апреля 2011

Я использую сетку данных WPF из codeplex. Я использую DatagridTemplateColumn и написал шаблоны данных для отображения содержимого в каждом столбце.

Теперь мне нужно отобразить какое-нибудь сообщение помощи пользователю, когда любой элемент управления в сетке данных сфокусирован. Для этого я подумал об использовании слоя adorner. Я использовал загруженное событие ComboBox и получил доступ к его слою adrorner. Затем я добавил свой собственный слой с надписью, который должен отображаться там, как подсказка. Ниже приведен код.

        TextBox txtBox = (TextBox)comboBox.Template.FindName("PART_EditableTextBox", comboBox);
        if (txtBox == null)
            return;

        txtBox.ToolTip = comboBox.ToolTip;
        AdornerLayer myAdornerLayer = AdornerLayer.GetAdornerLayer(txtBox);
        Binding bind = new Binding("IsKeyboardFocused");
        bind.Converter = new KeyToVisibilityConverter();
        bind.Source = txtBox;
        bind.Mode = BindingMode.OneWay;
        PEAdornerControl adorner = new PEAdornerControl(txtBox);
        adorner.SetBinding(PEAdornerControl.VisibilityProperty, bind);

PEAdorner слой это ::

  public class PEAdornerControl : Adorner
  {
    Rect rect;

    // base class constructor.
    public PEAdornerControl(UIElement adornedElement)
        : base(adornedElement)
    { }

    protected override void OnRender(DrawingContext drawingContext)
    {
          .....
    }
  }

Теперь проблема в следующем. Я прилагаю скриншот того, как это выглядит в датагрид. Если сетка данных имеет более 4 строк, все в порядке. Ниже приведен скриншот

Correct help text

Если в сетке данных меньше номеров строк, этот рекламный элемент попадает внутрь сетки данных и не виден пользователю. Снимок экрана ниже Half help text

Как мне получить этот слой с надписью над сеткой данных? Пожалуйста, помогите мне !!!

Ответы [ 2 ]

1 голос
/ 11 апреля 2011

Я снова посмотрел на ваш вопрос, и я думаю, что это то, что вам нужно.

    TextBox txtBox = (TextBox)comboBox.Template.FindName("PART_EditableTextBox", comboBox);
    if (txtBox == null)
        return;

    txtBox.ToolTip = comboBox.ToolTip;

    //this is locating the DataGrid that contains the textbox
    DataGrid parent = FindParent<DataGrid>(this);

    //Get the adorner for the parent
    AdornerLayer myAdornerLayer = AdornerLayer.GetAdornerLayer(parent);
    Binding bind = new Binding("IsKeyboardFocused");
    bind.Converter = new KeyToVisibilityConverter();
    bind.Source = txtBox;
    bind.Mode = BindingMode.OneWay;
    PEAdornerControl adorner = new PEAdornerControl(txtBox);
    adorner.SetBinding(PEAdornerControl.VisibilityProperty, bind);

Метод поиска родительского элемента такой:

public T FindParent<T>(DependencyObject obj) where T : DepedencyObject
{
  if (obj == null)
     return null;
  DependencyOBject parent = VisualTreeHelper.GetParent(obj);

  if (parent is T)
      return parent as T;
  else
      return FindParent<T>(parent);
 }

Возможно, вам потребуется установитьположение вашего рекламодателя в методе OnRender, но это должно сработать.Однако следует учитывать, что если ваша DataGrid находится внутри другого контейнера (например, панели, сетки и т. Д.), Вы все равно можете столкнуться с проблемой отсечения.

Проблема отсечения связана с тем, что когдаКонтейнер проверяет компоновку своих дочерних элементов, которые он обычно не учитывает.Для борьбы с этим вам, возможно, потребуется создать свой собственный элемент управления и переопределить метод MeasuerOverride (ограничение размера).

Пример:

public class MyPanel : Panel
{
   protected override Size MeasureOverride(Size constraint)
   {
     Size toReturn = new Size();
     foreach (UIElement child in this.InternalChildren)
     {
       //Do normal Measuring of children

       foreach( UIElement achild in AdornerLayer.GetAdorners(child))
       //Measure child adorners and add to return size as needed
     }

     return toReturn;
   }
 }

Этот код действительно груб для измерения, но должен указать вамв правильном направлении.Обратитесь к странице документации http://msdn.microsoft.com/en-us/library/system.windows.frameworkelement.measureoverride.aspx для получения информации об измерении дочерних элементов на панели.

0 голосов
/ 01 февраля 2016

Просто получите самый верхний AdornerLayer вместо

    static AdornerLayer GetAdornerLayer(FrameworkElement adornedElement)
    {
        var w = Window.GetWindow(adornedElement);
        var vis = w.Content as Visual;

        return AdornerLayer.GetAdornerLayer(vis);
    }

Кроме того, если у вас есть имя вашего DataGrid, вы можете получить ближайший слой над ним:

AdornerLayer myAdornerLayer = AdornerLayer.GetAdornerLayer(myDataGrid);
...