none
Problem when Convert Paul's blog: "Inject dynamically a column with data-aware icons in a lightswitch datagrid" to VB.Net RRS feed

  • Question

  • Hi, there!

    I'm trying to convert C# Paul's code to VB.Net (from Inject dynamically a column with data-aware icons in a lightswitch datagrid )

    I'm having problem with this convertion:

    C#:

    public partial class SearchCustomers
        {
            partial void SearchCustomers_Created()
            {
                //make sure to adapt the following predicate up to the logic you want !
                Predicate<Customer> predicate = (c) => c.Country.Equals("belgium", StringComparison.InvariantCultureIgnoreCase);
                this.FindControl("grid").InjectColumnWithIcon<Customer, Customer.DetailsClass>(predicate,"important.png");
            }
        }

    VB.Net: (this code compiles nice)

    Public Class SearchCustomers
    
            Private Sub SearchCustomers_Created()
    
                'make sure to adapt the following predicate up to the logic you want !
                Dim predicate As Predicate(Of Customer) = Function(c) c.Country.Equals("belgium", StringComparison.InvariantCultureIgnoreCase)
                Me.FindControl("grid").InjectColumnWithIcon(Of Customer, Customer.DetailsClass)(predicate, "important.png")
    
            End Sub
        End Class

    But, when I run the Application, I get the following error message:

    Any suggestion fo fix this problem?

    Best regards,


    Ciro

    Friday, August 17, 2012 8:48 PM

Answers

  • Indeed Justin,

    The problem is that in an editable grid "Show add new row" is standard checked, while in a search screen it is not. When Show add new row is one, the extension method is also trying to add an icon for the new row which is obviously empty.

    So, the code just needs a null check. Here is the updated extension method:

    public static class GridExtensions
        {
            public static void InjectColumnWithIcon<TEntity, TDetails>(this IContentItemProxy gridProxy, Predicate<TEntity> predicate, string imagefileName)
                where TEntity : EntityObject<TEntity, TDetails>
                where TDetails : EntityDetails<TEntity, TDetails>, new()
            {
                EventHandler<ControlAvailableEventArgs> gridProxy_ControlAvailable = null;
    
                gridProxy_ControlAvailable = (s1, e1) =>
                {
                    BitmapImage bitmapImage = GetBitmapImage(imagefileName);
                    DataGrid dataGrid = e1.Control as DataGrid;
                    var col = new DataGridTemplateColumn();
                    var xaml =
                        @"<DataTemplate xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"">
                          <Image Height =""25"" Width=""25""  />
                    </DataTemplate>";
    
                    var dataTemplate = XamlReader.Load(xaml) as DataTemplate;
                    col.CellTemplate = dataTemplate;
                    col.IsReadOnly = true;
                    dataGrid.Columns.Insert(0, col);
                    dataGrid.LoadingRow += new EventHandler<DataGridRowEventArgs>((s2, e2) =>
                    {
                        TEntity currentEntity = e2.Row.DataContext as TEntity;
                        if (currentEntity !=null && predicate(currentEntity))
                        {
                            DataGridColumn column = dataGrid.Columns[0];
                            Image image = column.GetCellContent(e2.Row) as Image;
                            image.Source = bitmapImage;
                        }
                    });
                    gridProxy.ControlAvailable -= gridProxy_ControlAvailable;
                };
    
                gridProxy.ControlAvailable += gridProxy_ControlAvailable;
            }
    
            private static BitmapImage GetBitmapImage(string fileName)
            {
                byte[] bytes = GetImageByName(fileName);
                using (MemoryStream ms = new MemoryStream(bytes))
                {
                    var bi = new BitmapImage();
                    bi.SetSource(ms);
                    return bi;
                }
            }
    
            private static byte[] GetImageByName(string fileName)
            {
                Assembly assembly = Assembly.GetExecutingAssembly();
                fileName = Application.Current.Details.Name + ".Resources." + fileName;
    
                using (Stream stream = assembly.GetManifestResourceStream(fileName))
                {
                    if (stream == null) return null;
                    byte[] buf = new byte[stream.Length];
                    stream.Read(buf, 0, (int)stream.Length);
                    return buf;
                }
            }
        }

    So, there is a "null check" in the loadingRow event on currentEntity.

        if (currentEntity !=null && predicate(currentEntity))

    thanks a lot for pointing me in the direction of this bug !

    paul.


    paul van bladel

    • Marked as answer by Oric.CQ Saturday, August 18, 2012 10:45 AM
    Saturday, August 18, 2012 6:38 AM

All replies

  • The value of the Country property for the particular Customer entity is probably null. Change:

    Function(c) c.Country.Equals("belgium", StringComparison.InvariantCultureIgnoreCase)

    to:

    Function(c) String.Equals(c.Country, "belgium", StringComparison.InvariantCultureIgnoreCase)


    Justin Anderson, LightSwitch Development Team

    Friday, August 17, 2012 9:08 PM
    Moderator
  • Hi, Justin! Thanks to reply.

    Unfortunately, the problem was not solved:

    BBefore open the screen, I add some fields to Customer table.

    BBest regards,


    Ciro

    Friday, August 17, 2012 9:29 PM
  • I think that Paul's solution only works with "Search Screen Template" (worked nice for me).

    I tried to use it with "Editable Grid Screen" template and I got an exception showed above.

    Best regards,


    Ciro

    Friday, August 17, 2012 10:09 PM
  • The only thing that I can think of is that the Customer that is passed into the function is null. You'll have to debug into InjectColumnWithIcon method to see why it is passing in null to the function.

    Justin Anderson, LightSwitch Development Team

    Friday, August 17, 2012 10:17 PM
    Moderator
  • Indeed Justin,

    The problem is that in an editable grid "Show add new row" is standard checked, while in a search screen it is not. When Show add new row is one, the extension method is also trying to add an icon for the new row which is obviously empty.

    So, the code just needs a null check. Here is the updated extension method:

    public static class GridExtensions
        {
            public static void InjectColumnWithIcon<TEntity, TDetails>(this IContentItemProxy gridProxy, Predicate<TEntity> predicate, string imagefileName)
                where TEntity : EntityObject<TEntity, TDetails>
                where TDetails : EntityDetails<TEntity, TDetails>, new()
            {
                EventHandler<ControlAvailableEventArgs> gridProxy_ControlAvailable = null;
    
                gridProxy_ControlAvailable = (s1, e1) =>
                {
                    BitmapImage bitmapImage = GetBitmapImage(imagefileName);
                    DataGrid dataGrid = e1.Control as DataGrid;
                    var col = new DataGridTemplateColumn();
                    var xaml =
                        @"<DataTemplate xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"">
                          <Image Height =""25"" Width=""25""  />
                    </DataTemplate>";
    
                    var dataTemplate = XamlReader.Load(xaml) as DataTemplate;
                    col.CellTemplate = dataTemplate;
                    col.IsReadOnly = true;
                    dataGrid.Columns.Insert(0, col);
                    dataGrid.LoadingRow += new EventHandler<DataGridRowEventArgs>((s2, e2) =>
                    {
                        TEntity currentEntity = e2.Row.DataContext as TEntity;
                        if (currentEntity !=null && predicate(currentEntity))
                        {
                            DataGridColumn column = dataGrid.Columns[0];
                            Image image = column.GetCellContent(e2.Row) as Image;
                            image.Source = bitmapImage;
                        }
                    });
                    gridProxy.ControlAvailable -= gridProxy_ControlAvailable;
                };
    
                gridProxy.ControlAvailable += gridProxy_ControlAvailable;
            }
    
            private static BitmapImage GetBitmapImage(string fileName)
            {
                byte[] bytes = GetImageByName(fileName);
                using (MemoryStream ms = new MemoryStream(bytes))
                {
                    var bi = new BitmapImage();
                    bi.SetSource(ms);
                    return bi;
                }
            }
    
            private static byte[] GetImageByName(string fileName)
            {
                Assembly assembly = Assembly.GetExecutingAssembly();
                fileName = Application.Current.Details.Name + ".Resources." + fileName;
    
                using (Stream stream = assembly.GetManifestResourceStream(fileName))
                {
                    if (stream == null) return null;
                    byte[] buf = new byte[stream.Length];
                    stream.Read(buf, 0, (int)stream.Length);
                    return buf;
                }
            }
        }

    So, there is a "null check" in the loadingRow event on currentEntity.

        if (currentEntity !=null && predicate(currentEntity))

    thanks a lot for pointing me in the direction of this bug !

    paul.


    paul van bladel

    • Marked as answer by Oric.CQ Saturday, August 18, 2012 10:45 AM
    Saturday, August 18, 2012 6:38 AM
  • I've modified the function for adding de column at the end of the grid and put a diferent icon if the predicate is not satisfied, not at the beggining. But I have a problem, the last row, wich is empty, is also getting an icon. Do you have any idea about how solve this issue?

    This is the modified function

    public static void InjectColumnWithIconTFFinal<TEntity, TDetails>(this IContentItemProxy gridProxy, Predicate<TEntity> predicate, string imagefileName)
                where TEntity : EntityObject<TEntity, TDetails>
                where TDetails : EntityDetails<TEntity, TDetails>, new()
            {
                EventHandler<ControlAvailableEventArgs> gridProxy_ControlAvailable = null;
    
                gridProxy_ControlAvailable = (s1, e1) =>
                {
                    BitmapImage bitmapImageTrue = GetBitmapImage(imagefileName +"True.png");
                    BitmapImage bitmapImageFalse = GetBitmapImage(imagefileName+"False.png");
                    DataGrid dataGrid = e1.Control as DataGrid;
                    var col = new DataGridTemplateColumn();
                    var xaml =
                        @"<DataTemplate xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"">
                          <Image Height =""25"" Width=""25""  />
                    </DataTemplate>";
    
                    var dataTemplate = XamlReader.Load(xaml) as DataTemplate;
                    col.CellTemplate = dataTemplate;
                    col.IsReadOnly = true;
                    var columnas = dataGrid.Columns.Count();
                    dataGrid.Columns.Insert(columnas, col);
                    dataGrid.LoadingRow += new EventHandler<DataGridRowEventArgs>((s2, e2) =>
                    {
                        TEntity currentEntity = e2.Row.DataContext as TEntity;
                        if (currentEntity != null)
                        {
                            DataGridColumn column = dataGrid.Columns[columnas];
                            Image image = column.GetCellContent(e2.Row) as Image;
                            if (predicate(currentEntity))
                            {
                                //Insert the "True" image
                                image.Source = bitmapImageTrue;
                            }
                            else
                            {
                                //Insert the "False" image
                                image.Source = bitmapImageFalse;
                            }
                            
                        }
                    });
                    gridProxy.ControlAvailable -= gridProxy_ControlAvailable;
                };
    
                gridProxy.ControlAvailable += gridProxy_ControlAvailable;
            }

    Best Regards, 

    Gabriel


    Thursday, October 25, 2012 11:27 PM
  • @Ciro - I just want to point out that a "Search Screen", & an "Editable Grid Screen" are essentially the same thing, but with some different default values, & a few properties set differently.

    Any screen that's added by one of those two templates can be changed into the other "type" of screen manually. In your case, disabling the datagrid's "Show Add New Row" would be all you needed. But checking for null, or using a different comparison method (as suggested by Justin) is a better way of handling it.


    Yann - LightSwitch Central - Click here for FREE Themes, Controls, Types and Commands
     
    If you find a reply helpful, please click "Vote as Helpful", if a reply answers your question, please click "Mark as Answer"
     
    By doing this you'll help people find answers faster.

    Friday, October 26, 2012 12:59 AM
    Moderator