4

我正在使用来自 codeplex 的 WPF 数据网格。我正在使用 DatagridTemplateColumn 并且我已经编写了数据模板来显示每列中的内容。

现在我必须在 datagrid 中的任何控件聚焦时向用户显示一些帮助消息。为此,我想到了使用装饰层。我使用了 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 行,一切都很好。下面是截图

正确的帮助文本

如果数据网格的行数较少,则此装饰器进入数据网格内部并且对用户不可见。截图如下 半帮助文本

如何在 DataGrid 上方获得这个装饰层?请帮我 !!!

4

2 回答 2

1

我再次查看了您的问题,我认为这就是您所需要的。

    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(Size constraint) 方法。

例子:

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以获取有关在面板中测量子元素的信息。

于 2011-04-11T14:25:33.560 回答
0

只是得到最上面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);
于 2016-01-31T23:15:32.457 回答