Tuesday, January 8, 2013

Tooltips to the max - expressive UI

UI simply depends on the smartness of our components. However the visible UI space is limited and most of the information is hidden behind components (tabs, popup forms etc). Therefore to display this hidden info user interaction is required. Tooltips however do not require any user interaction and our Suite supports tooltips with html formatting even in windows platform. We can already empower the detailed views of our XAF applications with native tooltip support as described in this help document. However when developing in XAF the sky’s the limit and in this post we will discuss ways to create tooltips as demoed in our XVideoRental RWA.

DataOnToolTip

By this we mean that we want to push any data a property of a business object has to a tooltip. Therefore, first we need to create a interface and extend our Application Model columns as described in our documentation,

[ModelAbstractClass]

public interface IModelColumnTooltipData : IModelColumn {

    IModelTooltipData TooltipData { get; }

}

public interface IModelTooltipData : IModelNode {

    [Category("DataOnToolTip")]

    bool DataOnToolTip { get; set; }

    [Category("DataOnToolTip")]

    int MaxHeight { get; set; }

    [Category("DataOnToolTip")]

    int MaxWidth { get; set; }

}

 

public class GridViewImageTextToolTipController : ViewController<ListView>, IModelExtender {

    public void ExtendModelInterfaces(ModelInterfaceExtenders extenders) {

        extenders.Add<IModelColumn, IModelColumnTooltipData>();

    }

The above will extend the Application Model as shown,

image

Next, we need to implement a method that when DataOnTooltip attribute is set will display the data in a tooltip like,

image

Of course due to the MVC XAF architecture it is really easy to reuse this functionality in any XAF project without not even one line of code!

ToolTipText

Now, how about a different case? Lets say that we have a complex Advanced Banded ListView and we want to guide end user to double click to a row area to see more info about the record. For this again we need to extend the Application Model with an attribute like,

    public interface IModelTooltipData : IModelNode {

        [Editor(typeof(MultilineStringEditor), typeof(UITypeEditor))]

        string ToolTipText { get; set; }

//        ...

Then we can use the Model Editor to assign the text we want in the ToolTipText attribute and XAF will do the rest for us in any project!

image

ToolTipController

Extending the Application Model in order to be able to associate a class (controller) with any of its nodes can be done easily. First we add one more property to our IModelToolTipData interface like,

public interface IModelTooltipData : IModelNode {

    [DataSourceProperty("ToolTipControllers")]

    [TypeConverter(typeof(StringToTypeConverterBase))]

    Type ToolTipController { get; set; }

 

    [Browsable(false)]

    IEnumerable<Type> ToolTipControllers { get; }

The TypeConverter attribute will convert the type to a string so it will be possible for the Model Editor to show it and the DataSourceProperty attribute will populate the Types (Controllers) we want. What's left is to decide which classes will be in that list. This can be done be writing a Domain Logic for the non browsable ToolTipControllers enumeration like the following,

[DomainLogic(typeof(IModelTooltipData))]

public class IModelToolTipControllerDomainLogic  {

    public static IEnumerable<Type> Get_ToolTipControllers(IModelToolTipController modelToolTipController) {

        return FindTypeDescenants(typeof(ObjectToolTipController));

    }

    protected static IEnumerable<Type> FindTypeDescenants(Type type) {

        var typeInfo = XafTypesInfo.Instance.FindTypeInfo(type);

        return ReflectionHelper.FindTypeDescendants(typeInfo).Where(info => !info.IsAbstract).Select(info => info.Type);

    }

 

}

 

We have finished Application Model extension so let’s see how simple yet amazingly powerful is to write and apply such a controller for our Movie business object. So for a very simple ToolTipController like,

public class MovieToolTipController : ObjectToolTipController {

    const int MaxPhotoWidth = 120, MaxPhotoHeight = 120;

    public MovieToolTipController(Control parent) : base(parent) { }

 

    protected override void InitToolTipItem(ToolTipItem item) {

        var movie = ObjectSpace.FindObject<Movie>(CriteriaOperator.Parse("MovieTitle=?", EditObject));

        var photo = movie.Photo;

        if (photo != null)

            item.Image = photo.CreateImage(MaxPhotoWidth, MaxPhotoHeight);

        item.Text = GetMovieInfoHtml(movie);

    }

    public string GetMovieInfoHtml(Movie movie) {

        return string.Format("<b>{0}</b>\r\n<i>{2:D}</i>\r\r\n{1}", movie.Title, movie.Plot, movie.ReleaseDate);

    }

 

}

When assign it to a listview column,

image

XAF will popup an html formatted tooltip,

image

or we can use a similar approach for PivotGridListEditors

image

Everything discussed in this post exist in the Common.Win project under the Common.Win.General.ToolTip namespace of our XVideoRental demo.

Let us know if you have questions or subjects we want us to cover. Happy XAFing to everybody!

Subscribe to XAF feed
Subscribe to community feed

DiggIt!

0 comments:

Post a Comment