Flexgrid WPF ImageCell Binding

Posted by: ray on 23 September 2022, 8:16 pm EST

    • Post Options:
    • Link

    Posted 23 September 2022, 8:16 pm EST - Updated 3 October 2022, 11:25 pm EST

    I want to know if this is possible:

    I want to build a WPF MVVM app bound to the viewmodel.

    I want to create a dataset of complex objects. I want to bind each flexgrid cell to each field in the dataset. This means, I want not only the displayed text but all of the fgcell properties to be set by the field they are attached to. As the status of the data fields change the cells will update as usual with INotifyPropertyUpdate.

    Example:

    If a Booking field is populated then the cell shows plain text with a white background and no image (or 1px transparent).

    The booking is updated, so the background changes to green and the image is a green tick.

    The booking is cancelled; the font is red and strike through, the bg is grey, and the image is a red “X”.

    The cells update every time just by updating the underlying dataset.

    Is this possible with this version of the control?

  • Posted 23 September 2022, 8:20 pm EST

    Also, can most of the same be done with the Headers?

  • Posted 26 September 2022, 11:17 pm EST

    Hi Raymond,

    You can create different data templates for each case of booking status and store them in the DataTemplateSelector class.

    Please see the following code snippet:

    
    <Window.Resources>
        <DataTemplate x:Key="unknownStatusTemplate">
            <TextBlock Text="{Binding Name}" />
        </DataTemplate>
        <DataTemplate x:Key="reservedTemplate">
            <StackPanel Orientation="Horizontal">
                <Image Source="/Resources/tick.png" Width="10" Height="10" VerticalAlignment="Center"/>
                <TextBlock Text="{Binding Name}" Background="Green" Width="100"/>
            </StackPanel>
        </DataTemplate>
        <DataTemplate x:Key="cancelledTemplate">
            <StackPanel Orientation="Horizontal">
                <Image Source="/Resources/x_mark.png" Width="10" Height="10" VerticalAlignment="Center"/>
                <TextBlock Text="{Binding Name}" Background="Gray"  Width="100" Foreground="Red" TextDecorations="Strikethrough"/>
            </StackPanel>
        </DataTemplate>
        <local:MyTemplateSelector x:Key="myDatatemplateSelector" UnknownStatusTemplate="{StaticResource unknownStatusTemplate}" 
                                  ReservedTemplate="{StaticResource reservedTemplate}" CancelledTemplate="{StaticResource cancelledTemplate}"/>
    </Window.Resources>
    
    

    And then override CellFactory’s CreateCellContent() method to set the content based on selected template as the following code:

    public override void CreateCellContent(C1FlexGrid grid, Border bdr, CellRange rng)
    {
       
        if (rng.Column == 1)
        {
            bdr.DataContext = (Booking)(grid.Rows[rng.Row].DataItem);
            bdr.Child = (System.Windows.UIElement)_myTemplateSelector.SelectTemplate((Booking)(grid.Rows[rng.Row].DataItem), grid).LoadContent();
        }
        else
        {
            base.CreateCellContent(grid, bdr, rng);
        }
    }
    
    

    Kindly refer to the attached sample for full implementation. ImageCellBindBooking.zip

    Best Regards,

    Aastha

  • Posted 11 October 2022, 5:48 am EST - Updated 11 October 2022, 5:53 am EST

    Hello Aastha.

    You appear to be working on a static column. I will be working on the cell that I click.

    I cannot seem to get past this error:

  • Posted 13 October 2022, 3:09 pm EST

    Hi Raymond,



    It seems like you are trying to bind your flexgrid with a DataTable, which is why you are getting the error shown in the snapshot provided by you. In this case, the DataItem returned will be of type DataRowView.

    Please see the following code:

    bdr.DataContext = (System.Data.DataRowView)(grid.Rows[rng.Row].DataItem);
    bdr.Child = (System.Windows.UIElement)_myTemplateSelector.SelectTemplate((System.Data.DataRowView)(grid.Rows[rng.Row].DataItem), grid).LoadContent();




    Please find attached the sample modified according to your requirement. ImageCellBindBooking_Mod.zip



    Regards,



    Aastha

  • Posted 21 October 2022, 11:09 pm EST

    Thanks Aastha. I’m not getting much time to work on this project atm. I did get your example to work but integrating it into my db is proving more difficult. I will put a couple of hours into it today.

    Thank you for your assistance.

  • Posted 22 October 2022, 2:34 am EST

    Aastha I need to intercept the cell that was clicked before hitting CreateCellContent

  • Posted 27 October 2022, 1:54 am EST

    Hello Aastha.

    I have looked hard at your code. You are binding to a defined column called “Status”. This is not possible for me. I need to bind the column or cell that the object is in. Look again at the image above that I supplied. The cell must get the information it needs from the object it contains.

    Can you help with this please. The documentation is not very friendly in this case.

    Thank you.

  • Posted 28 October 2022, 12:59 am EST

    Hi Raymond,

    Apologies for the delay in response.

    We are working on your requirement. Your patience is greatly appreciated while we work towards resolving this issue.

    Thanks and regards,



    Aastha

  • Posted 30 October 2022, 11:12 pm EST - Updated 31 October 2022, 2:30 am EST

    Hi Raymond,

    As per your requirement, we have created a sample that contains columns with Booking type objects whose template gets updated according to the ‘Status’ of the Booking object. Considering your use case, we have not defined any column for “Status”. In the attached sample, whenever you click on the cell with the ‘Booking’ type object, its template gets updated according to the information stored in the object it is bound to.

    It seems that you are using FlexGrid .NET6 control, hence we have updated the solution accordingly. We have overridden GridCellFactory’s PrepareCell() method to update the cells that have been clicked. Please see the following code snippet:

    public override void PrepareCell(GridCellType cellType, GridCellRange range, GridCellView cell, Thickness internalBorders)
    {
        if (_cells.Contains((range.Row, range.Column)))
        {
            cell.DataContext = (Booking)Grid[range.Row, range.Column];
            cell.Content = (FrameworkElement)_myTemplateSelector.SelectTemplate((Booking)Grid[range.Row, range.Column], Grid).LoadContent();
        }
        else
        {
            base.PrepareCell(cellType, range, cell, internalBorders);
        }
    }

    Note: In case you are working on .NET framework edition , you can implement this logic by overriding ApplyCellStyles() method of CellFactory class.

    Please refer to the attached sample for implementation. (See ImageCellTemplateBooking.zip)

    Regards,

    Aastha

  • Posted 2 November 2022, 12:35 am EST

    Hello Aastha.

    Thank you for the sample, I will look at it now.

    Re: “It seems that you are using FlexGrid .NET6 control…” I have purchased the latest version of WPF controls. I did find them difficult to get running. I assume from this comment that I am not using the correct version in my application?

  • Posted 2 November 2022, 8:31 pm EST

    Hi Raymond,

    Owning ComponentOne’s newest license entitles you to both the .NET and the .NET framework C1 controls. The APIs for both differ in their definition.

    You can use Flexgrid 4.5.2 and 4.6.2 version controls for building the .NET framework application and Flexgrid 6.0 controls for NET6 target applications.

    Since we were uncertain about which FlexGrid API you referred to in your project, we covered both cases in our comment.

    Moreover, we encourage you to build your application on NET 6.0 target framework as it is the latest long-term support release.

    Regards,

    Aastha

  • Posted 2 November 2022, 10:54 pm EST

    Hello Aastha.

    Yes I am targeting the latest frameworks; .Net6.0 , soon to be .Net 7.

    I see that “Flexgrid 6.0” in Nuget it is listed as C1.WPF.Grid I took that to mean it was something other than a flexgrid and that is the reason I used the 4.8. That matter is cleared up now. I have changed to C1.WPF.Grid

    Thank you for the code sample that you wrote for me. I am trying to find time to work on it. At a glance I see that the cells are passed in per click. Since my grid updates per change of calendar day and any changes to the underlying dataset, I will be hoping for the whole grid / cells to “format itself” on INotifyPropertyUpdate.

    Cheers,

    Ray.

  • Posted 28 March 2023, 4:53 am EST - Updated 28 March 2023, 4:58 am EST

    Hello Aastha!

    Sorry for having to reopen this can of worms. Due to the extreme complexity of trying to use this C1.WPF.Grid I had to shelve my project for months until now. I have actually considered doing it again in Windows Forms because this is so difficult.

    First thing I notice; in your demo app, if I double click on a blank cell and then click on a populated cell, the blank cell will be populated with false data. You can test this by clicking about like crazy.

    Also clicking on the Column Header or the top cell returns the same value. How do we tell if it is clicking the cell or the header?!

    The next thing is that this code relies on values being passed in 1 by 1. You click on the cell, determine which cell then add to the _cells collection (whatever that’s for) and then do the updates.

    Imagine if these were date dependent bookings and you want to click through the dates, each screen should appear already formatted.

    These grids destroy the idea of MVVM. It should be simple to apply any object to any cell or header.

    Binding should be as simple as Backcolor = “{Binding myObject.Color}”

    As it stands now I am trying to do everything in code behind just to make it work :frowning:

  • Posted 29 March 2023, 12:08 am EST

    Hi Raymond,

    The issue shown in the attached snapshot seems to be a bug in v6.0.20222.302 flexgrid control. In the latest version of flexgrid control, i.e. 6.0.20231.514, the issue seems to be fixed. We have attached a sample application for your reference. Please check ImageCellTemplateBooking_Mod.zip

    > Imagine if these were date dependent bookings and you want to click through the dates, each screen should appear already formatted.

    Regarding this concern, would it be possible for you to share the dataset you are currently working with? This would enable us to provide you with a tailored solution that meets your specific needs.

    Thanks & Regards,

    Aastha

  • Posted 29 March 2023, 3:28 am EST

    Hello Aastha.

    I have upgraded the control to latest and that got rid of the multi-clicking bug.

    Still if I click on the column header it will select the cell in row 0 - CellItem(0,2). What if I want to select the Header and not the cell?! This is not an issue for me now but should be something for you to consider.

    *…would it be possible for you to share the dataset * when I have enough time to break out the relevant parts of the code then maybe this is an option.

    For now I am resigned to trying to use Code Behind to loop through the dataset but the simplest things are terribly difficult.

    How to set the myGrid[3,4].BackgroundColor = Brushes.LightGreen is a nightmare.

    For some reason this is possible

         GridColumn col = new();
                    col.Header = "colhead " + i.ToString();


    but this is not

    row.Header = "rowhead " + mystring

    If I want to set the row I must hack into BindCellContent and not PrepareCell!?!

    I want to be able to set the cell style to a particular style. We have determined one way to do this using xaml and the GridCellFactory

            <DataTemplate x:Key="reservedTemplate">
                <StackPanel Orientation="Horizontal">
                    <Image Source="/tick.png" Width="10" Height="10" VerticalAlignment="Center"/>
                    <TextBlock Background="LightGreen" Width="100"/>
                </StackPanel>
            </DataTemplate>


    and then hack into PrepareCell, but!.. not before we add it to a cells Collection???

    Who wrote this grid? Certainly not the person the wrote the Grape City pages advertising the grid

    Easy XAML Styling

    All parts of the WPF datagrid control can be styled easily without having to customize complex XAML templates.
    Clearly this person has not tried to set the styling on anything in this grid.

    There is nothing at all easy about using this grid, I am actually thinking of abandoning it completely before I am forced to abandon my project.

    If the cell can display the default text of the object contained inside it then why can’t all the other properties be bound to that same object or another object?

    Why can’t a Row’s header and other properties not be accessed by the Row’s index?

    I really don’t know how much more time I should give to learning how to use this control and I fear wasting anymore time on the rest of the C1 controls in the package in case they are as equally convoluted to use.

    The support is great but I am relying on support for everything. It would be better if we just had a usable control to begin with. I think I will be looking for alternate solutions.

Need extra support?

Upgrade your support plan and get personal unlimited phone support with our customer engagement team

Learn More

Forum Channels