I have a requirement to add a clickable link to the title of the WinGrid. The link should open a default email client. I was looking at the following possible solution:
1. Create a widget containing wingrid with hidden title and place a label with link instead of title.
2. Generate bitmap for the title and add event handler which will open default email client.
3. Somehow customize WinGrid title, which I don't know how to do because it looks like it take basic Text type only.
What do you think would be be the best way to do it? Did you have similar requirements?
Thank you.
Brian,
Thanks for excellent example of CreationFilter. I am going to implement it next time we updating UI since it seems to be more elegant solution compare to hiding caption and adding formatted link label.
Thanks for the feedback, Mike.
I ended up using FormattedLinkLabel and hiding the caption since I don't really have much time to spend on it and FormattedLinkLabel does everything we need.
I originally set out to replace the TextUIElement in the caption area with a FormattedTextUIElement but the OnLinkClicked method never got called and it took less time to derive an element from TextUIElement and make it look like a link than it would have to try to figure out why the FormattedTextUIElement wasn't working. I'm sure I missed something simple so you can replace the LinkElement class here (see below) with that if you like:
this.ultraGrid.DisplayLayout.CaptionVisible = DefaultableBoolean.True;this.ultraGrid.CreationFilter = new GridCaptionLinkCreationFilter( "somebody@somewhere.com" );
#region LinkElement classpublic class LinkElement : TextUIElement{ public LinkElement( UIElement parentElement, string text ) : base( parentElement, text ){}
protected override void OnClick() { // TODO: Open link }
protected override void InitAppearance(ref AppearanceData appData, ref AppearancePropFlags flags) { if ( (flags & AppearancePropFlags.TextHAlign) == AppearancePropFlags.TextHAlign ) { flags &= ~AppearancePropFlags.TextHAlign; appData.TextHAlign = HAlign.Center; }
if ( (flags & AppearancePropFlags.FontUnderline) == AppearancePropFlags.FontUnderline ) { flags &= ~AppearancePropFlags.FontUnderline; appData.FontData.Underline = DefaultableBoolean.True; }
if ( (flags & AppearancePropFlags.ForeColor) == AppearancePropFlags.ForeColor ) { flags &= ~AppearancePropFlags.ForeColor; appData.ForeColor = SystemColors.HotTrack; }
if ( (flags & AppearancePropFlags.Cursor) == AppearancePropFlags.Cursor ) { flags &= ~AppearancePropFlags.Cursor; appData.Cursor = Cursors.Hand; }
base.InitAppearance(ref appData, ref flags); }}#endregion LinkElement class
#region GridCaptionLinkCreationFilter classprivate class GridCaptionLinkCreationFilter : IUIElementCreationFilter{ private string linkText = null; public GridCaptionLinkCreationFilter( string linkText ) { this.linkText = linkText; }
#region IUIElementCreationFilter Members
public void AfterCreateChildElements(UIElement parent) { CaptionAreaUIElement captionAreaElement = parent as CaptionAreaUIElement; if ( captionAreaElement != null ) { UIElement element = captionAreaElement.GetDescendant( typeof(TextUIElement) ); if ( element != null ) { Rectangle rect = element.Rect; captionAreaElement.ChildElements.Remove( element ); LinkElement linkElement = new LinkElement( captionAreaElement, this.linkText );
linkElement.Rect = rect; captionAreaElement.ChildElements.Add( linkElement ); } } }
public bool BeforeCreateChildElements(UIElement parent) { return false; }
#endregion}#endregion GridCaptionLinkCreationFilter class
EDIT
I just remembered what it was, you have to wrap the text you assign in an anchor (<a></a>) tag. So the LinkElement implementation then becomes this:
#region LinkElement classpublic class LinkElement : Infragistics.Win.FormattedLinkLabel.FormattedTextUIElement{ public LinkElement( UIElement parentElement, string text ) : base( parentElement) { this.Value = new Infragistics.Win.FormattedLinkLabel.ParsedFormattedTextValue(text); }
protected override void OnLinkClicked(Infragistics.Win.FormattedLinkLabel.LinkClickedEventArgs e) { base.OnLinkClicked(e); }
}#endregion LinkElement class
In my opinion, the easiest way to do this would be to turn off the grid's Caption and place a FormattedLinkLabel on top of the grid (option 1 as you listed above).
Option 2 - using a Bitmap, would also be fairly easy to implement, but it's probably not the best implementation since you won't get the hand cursor when you mouse over the link text and clicking will not give the proper visual that you should get when you click on something.
Option 3 would be the best option from a usability standpoint. But this would be a pretty complex and difficult CreationFilter to code, and I probably would not advise going this route unless you have a lot of time to spend on it.
I believe the best way is to create a customfilter. See IUIElementCreationFilter interface.