Dailycode.info

Short solution for short problems

Devexpress aspxgrid: Show dynamic images in a column (Part 2)

As I was using the grid in part 1, I noticed that the icon disappeared when I used sorting, or when I changed column places at runtime. This was because the HTML row created event was not called when these events happens, but a databind was done. At the moment I didn’t found a good solution, but then my colleague found a better way to databind image at runtime.

No more HTMLRowCreated event!

I improved the MyImageTemplate class that derives from the ITemplate.  There I take the databound object and directly check the property and select the image url. I added the public string property Function that will choose which dataitem to check and selects the correct function to check. You could make a ITemplate class for every column, or you could do it like this:

class MyImageTemplate : ITemplate

{

    public string ID { get; set; }

 

    public string Function { get; set; }

 

    public void InstantiateIn(Control container)

    {

        ASPxImage img = new ASPxImage();

        GridViewDataItemTemplateContainer gridContainer = (GridViewDataItemTemplateContainer)container;

        GridViewDataItemTemplateContainer ri = (GridViewDataItemTemplateContainer)gridContainer.NamingContainer;

        object dataValue =null ;

        try

        {

            dataValue = DataBinder.Eval(gridContainer.DataItem, Function);

        }

        catch { }

        img.ID = ID;

        img.ImageUrl = GetImageUrl(dataValue);

        container.Controls.Add(img);

    }

 

    private string GetImageUrl(object dataValue)

    {

        switch (Function.ToLower())

        {

            case "orderposshipmentready":

                return CheckOrderPosShipMentReady(dataValue);

            case "rushorder":

                return CheckRushOrder(dataValue);

            case "ordericon01":

                return CheckSpecial(dataValue);

            case "ordericon02":

                return CheckSize(dataValue);

            case "ordericon03":

                return CheckCoatingPrep(dataValue);

            default: return "";

        }

    }

 

    private string CheckOrderPosShipMentReady(object dataValue)

    {

        bool bShipmentReady = Convert.ToBoolean(dataValue);

 

        if (bShipmentReady)

        {

            return "~/Images/OK.gif";

        }

        else

        {

            return "~/Images/NOK.gif";

        }

    }

 

    private string CheckRushOrder(object dataValue)

    {

        bool check = false;

        try

        {

            if (dataValue.ToString() == "R")

            {

                check = true;

            }

        }

        catch { }

        if (check)

        {

            return "~/Images/rush.gif";

        }

        return "";

    }

 

 

 

    private string CheckSpecial(object dataValue)

    {

 

        bool check = false;

        try

        {

 

            if (dataValue.ToString() == "O0")

            {

                check = true;

            }

        }

        catch { }

        if (check)

        {

            return "~/Images/special.gif";

        }

        return "";

    }

 

    private string CheckSize(object dataValue)

    {

        bool check = false;

        try

        {

            if (dataValue.ToString() == "O1")

            {

                check = true;

            }

        }

        catch { }

        if (check)

        {

            return "~/Images/dikte.gif";

        }

        return "";

    }

 

    private string CheckCoatingPrep(object dataValue)

    {

        bool check = false;

        try

        {

            if (dataValue.ToString() == "O2")

            {

                check = true;

            }

        }

        catch { }

        if (check)

        {

            return "~/Images/paint.gif";

        }

        return "";

    }

}

 

The hardest part was to get the databound item from the row. Using the DataBinder.Eval function it had to work. Then it was just the case of getting the dataitem container that was bound. This code did the trick:

GridViewDataItemTemplateContainer gridContainer = (GridViewDataItemTemplateContainer)container;

GridViewDataItemTemplateContainer ri = (GridViewDataItemTemplateContainer)gridContainer.NamingContainer;

object dataValue =null ;

try

{

dataValue = DataBinder.Eval(gridContainer.DataItem, Function);

}

catch { }

 

Now to add this column at runtime, I simply create an instance of the MyImageTemplate and provide the 2 properties. Then the data binding does the rest:

GridViewDataColumn col1 = new GridViewDataColumn();

col1.Caption = ".";

col1.FieldName = property.Name;

col1.Width = Unit.Pixel(int.Parse(showColumns[count]));

col1.VisibleIndex = 0;

col1.DataItemTemplate = new MyImageTemplate() { ID = "ASPxImage1", Function="OrderPosShipmentReady" };

grdOrderLocations.Columns.Add(col1);

 

Now sorting and all other functions work! Be sure that the grid databind is called in the page load and not the page init.

 


Devexpress aspxgrid: Change row color at runtime

 

I needed to change the background color of a grid at runtime.

Found a good and easy solution on how to do this. You will need to override the HTMLRowPrepared event.

protected void grdOrderLocations_HtmlRowPrepared(object sender, DevExpress.Web.ASPxGridView.ASPxGridViewTableRowEventArgs e)

{

CheckBlocked(e);

}

 

private void CheckBlocked(ASPxGridViewTableRowEventArgs e)

{

    if (e.RowType != GridViewRowType.Data) return;

    object blocked = e.GetValue("BlockCodeIC");

    if (blocked != null)

        e.Row.BackColor = System.Drawing.Color.Red;

}

 

This is how it looks:


 


Devexpress aspxgrid: Show dynamic images in a column (Part 1)

There was a problem with this solution when you would use sorting or any other grid related function, the htmlrowcreated is only called when the grid is created, not after postback or callback. So together with a collegue I found a better way, this can be found in (Part 2)!

The challenge is to show images in a column, depending on the data, the image can be different. For example, when de Boolean is true, show OK.gif image, else show NOK.gif image. Or when a bool is set show an image, when it’s not set, show nothing.

 

Here an example of a grid containing several image columns that vary depending on data in that row.


 

The implementation involves 2 fazes. First we add the columns to our grid dynamically from the code behind, next we catch the HTMLRowCreated event were we set the image of the row. The first faze you also can be replaced if you put the columns in the aspx, but it gave me problems with the binding of the data. So I decided to create columns from the code behind. Before I data bind the data to the grid I create the columns from the code behind.

private void FillGrid(string id)

{

    List<Order> orderList = GenericSingleton<GMEntitiesPL>.GetInstance().GetOrdersOnLocation(id);

    grdOrderLocations.DataSource = orderList;

    AddCustomColumns(id);

    grdOrderLocations.DataBind();

    //grdOrderLocations.Columns[showColumns.Length].Visible = false;

}

 

In the AddCustomColumns, I will create all needed columns. Based on some data from the database, I decide which column to show. The interesting part here is where I create the 5 image columns:

Here the code to create the first image column:

GridViewDataColumn col1 = new GridViewDataColumn();

//TODO Set Header Value, Get them in TextTag from GP_MES_Translation on property.Name and use the default 

col1.Caption = "Order ready";

col1.FieldName = "OrderReady"; 

col1.Width = Unit.Pixel(int.Parse(showColumns[count]));

col1.VisibleIndex = 0;

//visibleIndex++; 

col1.DataItemTemplate = new MyImageTemplate() { ID = "ASPxImage1" };

grdOrderLocations.Columns.Add(col1);

 

We create a simple gridviewdatacolumn. Then we create a new ImageTemplate that will add the image to the dataitemtemplate of the column. Here fore I created a class that will instantiate a new class of the interface ITemplate:

class MyImageTemplate : ITemplate

    {

        public string ID { get; set; }

 

        public void InstantiateIn(Control container)

        {

            ASPxImage img = new ASPxImage();

            GridViewDataItemTemplateContainer gridContainer = (GridViewDataItemTemplateContainer)container;

            //img.ImageUrl = "~/Images/OK.gif";

            img.Visible = false;

            img.ID = ID;

            container.Controls.Add(img);

        }

    }

 

The class need the ID to be set, because this ID will be used later on to find the column and set the image.

When you add a next image column, you can use the same MyImageTemplate class, but give a different ID:

GridViewDataColumn col1 = new GridViewDataColumn();

//TODO Set Header Value, Get them in TextTag from GP_MES_Translation on property.Name and use the default 

col1.Caption = "Special";

col1.FieldName = "Special";

col1.Width = Unit.Pixel(int.Parse(showColumns[count]));

col1.VisibleIndex = 2;

//visibleIndex++; 

col1.DataItemTemplate = new MyImageTemplate() { ID = "ASPxImage3" };

grdOrderLocations.Columns.Add(col1);

 

So far so good, by now you should see the columns in the grid, but no image yet. This will be done in the HtmlRowCreated event of the grid:

protected void grdOrderLocations_HtmlRowCreated(object sender, DevExpress.Web.ASPxGridView.ASPxGridViewTableRowEventArgs e)

{

    //string index = e.VisibleIndex.ToString();

    CheckOrderPosShipMentReady(e);

    CheckRushOrder(e);

    CheckSpecial(e);

    CheckSize(e);

    CheckCoatingPrep(e);

}

 

I’ll show the first 2 functions. The first CheckOrderPosShipMentReady(e) will set a OK image if the Boolean value in the column is true else it will show a NOK image:

private void CheckOrderPosShipMentReady(ASPxGridViewTableRowEventArgs e)

{

    ASPxImage image = grdOrderLocations.FindRowCellTemplateControl(e.VisibleIndex, grdOrderLocations.Columns["orderready"] as GridViewDataColumn, "ASPxImage1") as ASPxImage;

 

    if (image == null) return;

    image.Visible = true;

    bool check = false;

    try

    {

        object b = e.GetValue("OrderReady");

        check = bool.Parse(b.ToString());

    }

    catch { }

    if (check)

    {

        image.ImageUrl = "~/Images/OK.gif";

        image.ToolTip = "Ready";

    }

    else

    {

        image.ImageUrl = "~/Images/NOK.gif";

        image.ToolTip = "Not ready";

    }

}

 

The next function will show an image if a property is filled else the image will stay visible false.

private void CheckSpecial(ASPxGridViewTableRowEventArgs e)

{

    ASPxImage image = grdOrderLocations.FindRowCellTemplateControl(e.VisibleIndex, grdOrderLocations.Columns["special"] as GridViewDataColumn, "ASPxImage3") as ASPxImage;

 

    if (image == null) return;

 

    bool check = false;

    try

    {

        object b = e.GetValue("Special");

        if (b.ToString() == "O0")

        {

            check = true;

        }

    }

    catch { }

    if (check)

    {

        image.Visible = true;

        image.ImageUrl = "~/Images/special.gif";

        image.ToolTip = "Rush Order";

    }

 

}

 

It’s working really well, I will continue to explore the grids functionality, combining it will the grid focused events etc… I’ll keep things posted here on the forum!