WPF shows how to render AdornerLayer on top of a DataGrid

I am using a WPat datagrid from codeplex. I am using a DatagridTemplateColumn and I have written data tables to display the content in each column.

Now I need to display some help message for the user when any control in the datagrid is concentrated. For this, I thought about using an adorner layer. I used the event loaded by ComboBox and got access to the adrorner layer. Then I added my own adorner layer so that something would appear there, similar to a tooltip. Below is the code.

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 Level:

  public class PEAdornerControl : Adorner { Rect rect; // base class constructor. public PEAdornerControl(UIElement adornedElement) : base(adornedElement) { } protected override void OnRender(DrawingContext drawingContext) { ..... } } 

Now the problem is as follows. I am attaching a screenshot of how it looks in a datagrid. If the datagrid has more than 4 rows, everything is fine. Below is a screenshot

Correct help text

If the datagrid has fewer rows, this adorner enters the datagrid and is not displayed to the user. Screenshot below Half help text

How to get this adorner layer over a DataGrid? Please help me!!!

+4
source share
2 answers

I looked at your question again, and I think this is what you need.

  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); 

Parent Search Method:

 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); } 

You may need to set the position of your adorner in the OnRender method, but this should work. However, it is worth considering that if your DataGrid is in another container (for example, a panel, grid, etc.), you may encounter a clipping problem.

The clipping problem is related to the fact that when a container checks the location of its children, it usually does not take into account their decorations. To combat this, you may need to create your own control and override the MeasuerOverride (size) method.

Example:

 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; } } 

This code is really rude to measure, but should point you in the right direction. Check the documentation page http://msdn.microsoft.com/en-us/library/system.windows.frameworkelement.measureoverride.aspx for information on measuring child elements in a panel.

+1
source

Just get the topmost AdornerLayer instead

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

In addition, if you have the name of your DataGrid , you can get the following layer above it:

 AdornerLayer myAdornerLayer = AdornerLayer.GetAdornerLayer(myDataGrid); 
-1
source

Source: https://habr.com/ru/post/1347245/


All Articles