Hello,
I'm currently adding UltraExplorerBarGroups to an UltraExplorerBar by dragging items from an UltraTree. What I'd like to do is show a drop location indicator in the explorer bar when I'm adding a new item in between existing items. Basically, the same indicator when you drag groups around to rearrage their order. Thanks.
Thanks again Brian. When AfterCreateChildElements is called and we get the child elements of the target ItemAreaInnerUIElement:
UIElementsCollection childElements = itemAreaElement.ChildElements;
childElements.Count is always 0, so the code in foreach never gets executed. Even when I modify the code so the DropHighlightElement object gets added as a child element, nothing is ever drawn.
A modified version that gets the line to draw, but I don't feel like the code is correct going by your previous posts and sample code. Am I doing something wrong here?
void IUIElementCreationFilter.AfterCreateChildElements(UIElement parent){ // Kind of works. if (this.isDragging == false) return;
ItemAreaInnerUIElement itemAreaElement = parent as ItemAreaInnerUIElement;
if (itemAreaElement != null) { Point cursorPos = this.explorerBar.PointToClient(Control.MousePosition);
UltraExplorerBarGroup group = parent.GetContext(typeof(UltraExplorerBarGroup)) as UltraExplorerBarGroup;
// Hit test each group to see if the cursor is currently over it Rectangle groupRectangle = group.UIElement.Rect;
if (groupRectangle.Contains(cursorPos)) { DropHighlightElement dropHighlightElement = new DropHighlightElement(itemAreaElement);
Rectangle rect = groupRectangle; rect.Height = 2; rect.Y = rect.Top; dropHighlightElement.Rect = rect;
// Feels like I'm adding dropHighlightElement to the wrong UIElement here. group.UIElement.ChildElements.Add(dropHighlightElement); } }}
There is code in the ItemDropHighlightUIElement class that checks to make sure an internal drag is in progress, which in your case it won't be, so recommending you use that was a bad idea.
The following code sample demonstrates how to implement the IUIElementCreationFilter interface to display a drop indicator when something is being dragged over the ExplorerBar:
#region ItemDragIndicatorCreationFilter/// <summary>/// IUIElementCreationFilter implementation which displays an item drop indicator/// when a drag operation which originated from a different control is in progress/// and the cursor is positioned over an ItemUIElement./// </summary>public class ItemDragIndicatorCreationFilter : IUIElementCreationFilter, IDisposable{ #region Member variables private UltraExplorerBar explorerBar = null; private bool isDragging = false; #endregion Member variables
#region Constructor /// <summary> /// Creates a new instance of the class. /// </summary> public ItemDragIndicatorCreationFilter( UltraExplorerBar explorerBar ) { this.explorerBar = explorerBar;
// Hook the DragEnter, DragLeave, and DragOver events so we // can listen for things being dragged over the ExplorerBar. this.HookDragEvents( true ); }
#endregion Constructor
#region HookDragEvents private void HookDragEvents( bool hook ) { if ( this.explorerBar == null ) return;
if ( hook ) { this.explorerBar.DragEnter += new DragEventHandler(explorerBar_DragEnter); this.explorerBar.DragLeave += new EventHandler(explorerBar_DragLeave); this.explorerBar.DragOver += new DragEventHandler(explorerBar_DragOver); } else { this.explorerBar.DragEnter -= new DragEventHandler(explorerBar_DragEnter); this.explorerBar.DragLeave -= new EventHandler(explorerBar_DragLeave); this.explorerBar.DragOver -= new DragEventHandler(explorerBar_DragOver); } } #endregion HookDragEvents
#region Drag events void explorerBar_DragLeave(object sender, EventArgs e) { this.isDragging = false; }
void explorerBar_DragEnter(object sender, DragEventArgs e) { this.isDragging = true; } private void explorerBar_DragOver(object sender, DragEventArgs e) { this.explorerBar.UIElement.DirtyChildElements( true ); } #endregion Drag events
#region IUIElementCreationFilter implementation
void IUIElementCreationFilter.AfterCreateChildElements(UIElement parent) { if ( this.isDragging == false ) return;
if ( itemAreaElement != null ) { // Get the current mouse position in client coordinates Point cursorPos = this.explorerBar.PointToClient( Control.MousePosition );
// Iterate the child elements and add the drop indicator // when we hit the drop target item UIElementsCollection childElements = itemAreaElement.ChildElements;
foreach( UIElement element in childElements ) { // If this element is not an ItemUIElement, skip it ItemUIElement itemElement = element as ItemUIElement; if ( itemElement == null ) continue;
// Hit test each item element to see if the cursor is currently over it Rectangle itemElementRect = itemElement.Rect; if ( itemElementRect.Contains(cursorPos) ) { // Create the DropHighlightElement DropHighlightElement dropHighlightElement = new DropHighlightElement(itemAreaElement);
// Calculate the Rect and set it (note that this is simplified for the sake of brevity) Rectangle rect = itemElementRect; rect.Height = 5; rect.Y = itemElementRect.Top - 5; dropHighlightElement.Rect = rect;
// Add it to the ItemAreaInnerUIElement's ChildElements collection childElements.Add( dropHighlightElement ); break; } } } }
bool IUIElementCreationFilter.BeforeCreateChildElements(UIElement parent) { return false; }
#endregion IUIElementCreationFilter implementation
#region IDisposable Members
void IDisposable.Dispose() { this.HookDragEvents( false ); this.explorerBar = null; }
#endregion
#region DropHighlightElement class public class DropHighlightElement : UIElement { public DropHighlightElement( UIElement parent ) : base( parent ){}
protected override void DrawBackColor(ref UIElementDrawParams drawParams) { // Do nothing so no background is drawn }
protected override void DrawForeground(ref UIElementDrawParams drawParams) { using( SolidBrush brush = new SolidBrush(Color.Red) ) { // Note that this is simplified for the sake of brevity drawParams.Graphics.FillRectangle( brush, this.Rect ); } } } #endregion DropHighlightElement class}#endregion ItemDragIndicatorCreationFilter
Ok,
I've had a chance to implement this using the DrawFilter and had a few questions.
1. Is there a "correct" way to flag which UltraExplorerBarGroup that will need the drop highlight? Just to test things out, all I did was modify the text displayed for the group item that I wanted the highlight on to "highlight this" and tested against that in my GetPhasesToFilter method, but that's obviously not the clean way to do things.
2. I tried for the life of me to create an ItemDropHighlightUIElement object, but couldn't figure out what its constructor is supposed to take as a second parameter. It's supposed to take a ItemUIElement, but I can't figure out what that's supposed to be exactly. What my code looks like:
public void AfterCreateChildElements(Infragistics.Win.UIElement parent){ if (parent is ItemAreaInnerUIElement) { ItemAreaInnerUIElement itemAreaInnerUIElement = parent as ItemAreaInnerUIElement;
ItemDropHighlightUIElement idh = new ItemDropHighlightUIElement(itemAreaInnerUIElement, ?);
parent.ChildElements.Add(idh);
} }
Any input provide would be greatly appreciated. Thanks.
Thanks for the response Brian. I haven't actually verified that this will work (clicked the wrong link), but I feel that I'm headed down the right path now. It'll take me some time to actually implement though it since I'm new to Infragistics controls.
This can be done using either the IUIElementDrawFilter or IUIElementCreationFilter interfaces. The UltraTree samples that ship with the SDK include an UltraTree example of the IUIElementDrawFilter approach, which demonstrates the concept, but it refers to UltraTree rather than UltraExplorerBar.
To quickly explain how this could be done with a creation filter: There is already a UIElement class (ItemDropHighlightUIElement) that does the drawing, which you could use (to be honest it is a very simple element and using it will not save you a huge amount of time over creating your own). When you implement IUIElementCreationFilter, you would add one of these elements to the ItemAreaInnerUIElement's ChildElements collection. To know where it goes, you would have to track the item closest to the cursor position, which you can use the ItemFromPoint method to do.