SfDataGrid Column Mapping to child ObservableCollection property / IsHidden Binding

Using a custom userControl in an UWP app, I would like to fill a HorizontalDataGrid with data. Attempts at accessing child properties dynamically, have been unsuccessfull so far:

When using a sfDataGrid and binding the ItemSource to an ObservableCollection of DataGridRowElements, mapping the columns for the properties of the "DataGridRowElement" works fine. However, the DataGridRowElements themselves have a property of another ObservableCollection of VisibleElements. I want to display all elements of the nested property VisibleElements (or AllElements) as normal columns next to the other properties of the DataGridRowElement.Is there a way to accomplish this dynamically, as the amount of members of VisibleElements is variable?
I can access the members of VisibleElements when hardcoding the MappingName <syncfusion:GridTextColumn  MappingName="VisibleElements[0].Content" /> but this is obviously non-dynamic. Can this be accomplished in Xaml and not CodeBehind, as I am using MVVMLight?

Things tried so far:
Using AutoGenerateColumns & AutoGenerateColumnsForCustomType. -> Works for all normal properties but not for the VisibleElement ObservableCollection.
Using the Master-DetailsView, I can automatically access all members of VisibleElements, however the data needs to be displayed as "normal" columns next to the other properties and not a DetailsView.



Another question regarding the IsHidden property of the columns:

Some columns should be visible based on a public boolean property given in the code behind of the userControl HorizontalDataGrid.

 <syncfusion:GridNumericColumn MappingName="Median" FormatString="F2"
                        IsHidden="{Binding Path=MedianVisibility ,ElementName=root}" />

However the column is always shown, no matter the state of the MedianVisibility property.

Please find the attached file, where the source code for the relevant controls and classes are given.
Thank you in advance


Attachment: Syncfusion_Support_Request_9d44bcfd.rar

15 Replies 1 reply marked as answer

MA Mohanram Anbukkarasu Syncfusion Team February 25, 2021 02:34 PM UTC

Hi Ole Valler, 

Thanks for contacting Syncfusion support.  

We are little unclear with your scenario. The number of record rows in the DataGrid will be decided based on the items in the underlying collection bounded to the DataGrid. In your scenario, you have mentioned that all the items in the VisibleElements collection are also need to be displayed in the main grid and not as a child grid. You have also mentioned that the number of items in the VisibleElements is variable. We are unclear about the requirement. If possible Kindly provide more details about the scenario and your requirement with image illustration. It will be more helpful for us to understand the exact scenario and to provide a prompt solution at earlier.  

Regards, 
Mohanrma A. 



OV Ole Valler February 26, 2021 07:56 AM UTC

Hi Mohanrma A.,

please find the attached visualization of what I am aiming for.

There seems to be a slight misunderstanding: there is no problem with the varying number of rows, this is working correctly.

The number of columns in the VisibleElements will vary, which is why they cannot be hardcoded. In the beginning, there will be no members in the VisibleElements. Later there will be some members added and for each row there will be different values. Think of the VisibleElement columns as measurements. In the beginning there is no data. Then you perform a measurement and add the data in the first column of VisibleElements. For each DataGridRowElement there will be a different value. The next measurement data is then displayed in the second column of VisibleElements, and so on.

The entries in the VisibleElements belong to each row, that’s why they are a child property of said row. The row properties of standard deviation, average etc. are based on the members of VisibleElements for each row.

I hope this explanation is helpful for understanding the situation, if you have additional questions please ask.

Regards,


Ole Valler


Attachment: DataGridView_7bbf5e8c.rar


MA Mohanram Anbukkarasu Syncfusion Team March 1, 2021 02:03 PM UTC

Hi Ole Valler, 

Thanks for the update.  

We are able to understand your scenario. You can achieve your requirement to add columns to the DataGrid based on the number of items in the VisibleElements collection in each row by iterating all the items in the Underlying collection and add the columns in code behind as shown in the following code example.  

Code example :  

var visibleElementCount = 0; 
 
 foreach(var item in itemsSourceCollection) 
 { 
     if (item.VisibleElements.Count > visibleElementCount) 
         visibleElementCount = item.VisibleElements.Count; 
 } 
 
 
 for (int i = 0; i < visibleElementCount; i++) 
 { 
     this.dataGrid.Columns.Add(new GridTextColumn() 
     { 
         MappingName = "VisibleElements[" + i + "].Content", 
         UseBindingValue = true, 
     }); 
 } 
  
We have prepared a simple sample to replicate this scenario and it is available in the following link for your reference.  


Please let us know if you require any other assistance from us.  

Regards, 
Mohanram A. 


Marked as answer

OV Ole Valler March 2, 2021 08:10 AM UTC

Hi Mohanram A.,

Thank you very much for your solution. I'll try to adapt it into out UWP MVVM application and will get back to you.

I guess there is no way to bind to an (at compile time) unknown amount of columns in Xaml and not in codeBehind?





OV Ole Valler March 2, 2021 12:48 PM UTC

Hi Mohanrma A.,

I got most of the functionality working; unfortunately not everything yet.
Could you please adapt your solution so that the header for the VisibleElements columns contains two vertically stacked controls: a checkbox and a button, with the content of the button to be the ColumnIndex of the VisibleElement?

Thank you in advance,
Ole Valler


OV Ole Valler March 2, 2021 01:09 PM UTC

Also, could you please show me where I would add a converter?
In my initial hardcoded implementation in Xaml I used the DisplayBinding property.

DisplayBinding ="{Binding Path=VisibleElements[1].Content, Converter={StaticResource AnalysisDecimalToStringConverter}}"

How can I do this in Codebehind?

Thanks


MA Mohanram Anbukkarasu Syncfusion Team March 3, 2021 01:17 PM UTC

Hi Ole Valler, 

Thanks for the update.  

As you have mentioned, it is not possible to add unknown amount of columns in Xaml. You can add only in code behind. You can create DisplayBinding with coverter in the code behind while adding the columns as shown in the following code example.  

Code example  

for (int i = 0; i < visibleElementCount; i++) 
{ 
    this.dataGrid.Columns.Add(new GridTextColumn() 
    { 
        MappingName = "VisibleElements[" + i + "].Content", 
        UseBindingValue = true, 
        DisplayBinding = new Binding() { Converter = new AnalysisDecimalToStringConverter(), Path = new PropertyPath("VisibleElements[" + i + "].Content") } 
    }); 
} 


We are little unclear with the requirement “Could you please adapt your solution so that the header for the VisibleElements columns contains two vertically stacked controls: a checkbox and a button, with the content of the button to be the ColumnIndex of the VisibleElement?” Kindly provide more details about this requirement with image illustration. It will be more helpful for us to understand the exact requirement and to provide a prompt solution at earlier.  

Regards, 
Mohanram A. 



OV Ole Valler March 3, 2021 03:29 PM UTC

Hi Mohanram A.,

thanks for the quick solution!

Please find the attached Image.
The header for each column (only for members of VisibleElements, not for the statistic columns) should contain two items, one checkbox and one Button as in the provided image. When pressing the button, I want to execute a command and use the ColumnIndex as the commandparameter.

Thank you and kind regards,
Ole Valler


Attachment: ColumnHeader_dbff7b46.rar


OV Ole Valler March 4, 2021 09:50 AM UTC

As an additional request, I would like to change the fontcolor in the Av colum based on another boolean property (IsSaturated) via a binding.
In Xaml I would do it like this:

<TextBlock    Text="{x:Bind Path=Name}"
                               Foreground="{Binding Path=IsSaturated, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource SaturationToColorConverter}}" />

How can I accomplish this in Codebehind, when adding the columns to the grid?

SfDataGrid.Columns.Add(new GridTextColumn()
            {
                MappingName = mappingName,
                UseBindingValue = useBindingValue,
                CellStyle = new Style() { new Binding() { Converter = new BoolToColorStyleConverter(), Path = new PropertyPath("IsSaturated") } }
            });

I assume I have to use the CellStyle property and add a new style, where I can then assign a color to the ForegroundProperty, based on the boolean property "IsSaturated", but struggle to implement this.


MA Mohanram Anbukkarasu Syncfusion Team March 4, 2021 09:51 AM UTC

Hi Ole Valler, 

Thanks for the update.  

You can achieve this requirement by using GridColumn.HeaderTemplate property as shown in the following code example.  

Code example :  

<Page.Resources> 
     <local:ColumnNameToColumnIndexConverter x:Key="ColumnNameToColumnIndexConverter"/> 
     <DataTemplate x:Key="headerTemplate"> 
         <StackPanel> 
             <Button Width="40" Content="X" Command="{Binding }" /> 
             <CheckBox Width="40" IsChecked="True" Content="{Binding Converter={StaticResource ColumnNameToColumnIndexConverter}}"/> 
         </StackPanel> 
     </DataTemplate> 
 </Page.Resources> 
 
 
for (int i = 0; i < visibleElementCount; i++) 
{ 
    this.dataGrid.Columns.Add(new GridTextColumn() 
    { 
        MappingName = "VisibleElements[" + i + "].Content", 
        UseBindingValue = true, 
        DisplayBinding = new Binding() { Converter = new AnalysisDecimalToStringConverter(), Path = new PropertyPath("VisibleElements[" + i + "].Content") }, 
        HeaderTemplate = this.Resources["headerTemplate"] as DataTemplate 
    }); 
} 

public class ColumnNameToColumnIndexConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, string language) 
    { 
        var splitedItems = value.ToString().Split(new char[] { '[', ']' }); 
        return splitedItems[1]; 
    } 
 
    public object ConvertBack(object value, Type targetType, object parameter, string language) 
    { 
        throw new NotImplementedException(); 
    } 
} 


Please let us know if you require further assistance from us.  

Regards, 
Mohanram A. 



MA Mohanram Anbukkarasu Syncfusion Team March 4, 2021 10:07 AM UTC

Hi Ole Valler, 
  
You can change the style for the cells conditionally using CellStyleSelector property. Please refer the below given help documentation.  


Please let us know if you require any other assistance from us.  

Regards, 
Mohanram A. 



OV Ole Valler March 4, 2021 01:33 PM UTC


Hi Mohanrma A. ,

thank you for your solution. Unfortunately, I cannot achieve the desired functionality with it yet. I did manage to set the content of the checkbox to the columnIndex using your converter. However, I wanted to achieve this by binding to the actual property ColumnIndex, as I wanted to be shown how to access the properties of the VisibleElement.
This is necessary because I want to (Two-Way) bind the IsChecked property of the checkbox to the IsChecked Property of the VisibleElements. Therefore, I need to access the properties of the VisibleElements inside the DataTemplate.

Here is pseudo code describing the functionality (Not workling like this):

      <DataTemplate x:Key="headerTemplate" x:DataType="local:VisibleElement>
            <StackPanel>
                <Button Width="40" Content="X" Command="{Binding}" CommandParameter="{Binding ColumnIndex}" />
                <CheckBox Width="40" IsChecked="{Binding IsChecked, Mode=TwoWay}" Content="{Binding ColumnIndex}"/>
            </StackPanel>
        </DataTemplate>

where IsChecked and ColumnIndex are public properties of VisibleElement. 

I receive the following error:
BindingExpression path error: 'IsChecked' property not found on 'Windows.Foundation.IReference`1<String>'           



For my second question: Looking at the provided documentation, I need to achieve the following:

<syncfusion:GridTextColumn MappingName="OrderID">
            <syncfusion:GridTextColumn.CellStyle>
                <Style TargetType="syncfusion:GridCell">
                    <Setter Property="utils:SetterValueBindingHelper.PropertyBinding">
                        <Setter.Value>
                            <utils:SetterValueBindingHelper Property="Background" Binding="{Binding OrderID,Converter={StaticResource converter}}"/>
                        </Setter.Value>
                    </Setter>
                </Style>
            </syncfusion:GridTextColumn.CellStyle>
        </syncfusion:GridTextColumn>

in CodeBehind. I cant do it in Xaml as the column mappings are variable. How do I achieve this?


MA Mohanram Anbukkarasu Syncfusion Team March 5, 2021 01:59 PM UTC

Hi Ole Valler 

Thanks for the update.  

We are currently validating this. We will check and update with further details on March 9, 2021. We appreciate your patience until then.   

Regards,  
Mohanram A. 



MA Mohanram Anbukkarasu Syncfusion Team March 9, 2021 02:04 PM UTC

Hi Ole Valler 

We regret for the inconvenience.  

We are still validating this. We will check and update with further details on March 11, 2021. We appreciate your patience and understanding.   

Regards,   
Mohanram A. 



MA Mohanram Anbukkarasu Syncfusion Team March 11, 2021 01:15 PM UTC

Hi Ole Valler 

Thanks for your patience.  

We have checked the possibilities. You can create the template and use it is code behind using StringBuilder. Please refer c# tab in the below given help documentation.  


Regards, 
Mohanram A. 


Loader.
Up arrow icon