This is a migrated thread and some comments may be shown as answers.

Aggregate Function SourceField Path

6 Answers 177 Views
GridView
This is a migrated thread and some comments may be shown as answers.
Miguel Peixoto
Top achievements
Rank 1
Miguel Peixoto asked on 16 Nov 2010, 11:01 AM
Hi,

Is it possible to have the aggregate function's source field pointed to a Path?
My data source is generated dynamically so I'm trying to use the Path approach like in DataMemberBinding.

Thanks.


<
telerik:GridViewDataColumn Header="Field 1" Width="120" 
      DataMemberBinding="{Binding Mode=TwoWay, Path=Columns[1]}" DataFormatString="{}{0:N2}" >
    <telerik:GridViewDataColumn.AggregateFunctions>
       <telerik:SumFunction Caption="Sum: " SourceField="{Path=Columns[1]}" ResultFormatString="{}{0:N2}"/>
    </telerik:GridViewDataColumn.AggregateFunctions>
</telerik:GridViewDataColumn>

6 Answers, 1 is accepted

Sort by
0
Pavel Pavlov
Telerik team
answered on 16 Nov 2010, 11:42 AM
Hi Miguel Peixoto,

Depending on the implementation of the objects in your collection this can be achieved either by setting  the source field correctly or by using a custom aggregate function .

You are saying the source objects are build dynamically. Can you please paste me the code of your objects and the one used to dynamically create /populate these objects .

I will need this to point you in the right direction .

Kind regards,
Pavel Pavlov
the Telerik team
See What's New in RadControls for WPF in Q3 2010 on Tuesday, November 16, 2010 11:00 AM - 12:00 PM EST or 10:00 PM - 11:00 PM EST: Register here>>
0
Miguel Peixoto
Top achievements
Rank 1
answered on 16 Nov 2010, 04:02 PM
Hi Pavel,

This is how set the DataContext:

private void SetTableValues()
{              
    radDataGrid.DataContext = BusinessServices.MyService.GetTable();
}

Now the GetTable method returns an ObservableCollection (MyTable) which in turn is populated with a Xml (which inner data represents a table but is dynamic):

public MyTable GetTable()
{
    try
    {       
        XElement tableXml = XElement.Parse(this.GetXML());
  
        int numberOfColumns = tableXml.Elements("tc").Count();
        int numberOfRows = tableXml.Element("tc").Nodes().Count();
  
        MyTable table = new MyTable();
  
        if (numberOfRows > 0)
        {
            for (int i = 0; i < numberOfRows; i++)
            {
                ObservableCollection<string> list = new ObservableCollection<string>();
  
                for (int j = 0; j < numberOfColumns; j++)
                {
                    list.Add(ReadTableValue(tableXml, i, j));
                }
  
                table.Add(new MyTableRow(list));
            }
        }
        else
        {
            table.Add(new MyTableRow());
        }
  
        return table;
    }
    catch (XmlException ex)
    {
        if (BusinessModelExceptionHandler.HandleXmlException(ex))
        {
            throw;
        }
    }
    catch (Exception ex)
    {
        if (BusinessModelExceptionHandler.HandleBusinessException(ex))
        {
            throw;
        }
  
        return null;
    }
}

And the MyTable and MyTableRow classes:

public class MyTable : ObservableCollection<MyTableRow>
{        
    public bool IsEmpty()
    {
        ....
    }
      
    public bool IsEqual(object value)
    {
        ...
    }
}
  
/// <summary>
/// Class containing a table row data.
/// </summary>
public class MyTableRow : INotifyPropertyChanged
{
    /// <summary>
    /// Initializes a new instance of the <see cref="MyTableRow"/> class.
    /// </summary>
    public MyTableRow()
    {
        this.Columns = new ObservableCollection<string>();
  
        for (int i = 1; i <= 50; i++)
        {
            this.Columns.Add(string.Empty);
        }
    }
  
    /// <summary>
    /// Initializes a new instance of the <see cref="MyTableRow"/> class.
    /// </summary>
    /// <param name="columns">The columns.</param>
    public MyTableRow(ObservableCollection<string> columns)
    {
        this.Columns = columns;
    }
  
    /// <summary>
    /// Occurs when a property value changes.
    /// </summary>
    public event PropertyChangedEventHandler PropertyChanged;
  
    public ObservableCollection<string> Columns { get; set; }
  
}

As you can see, this is quite simple. But I can't understand why the Path=Columns[x] can't be used in the aggregate SourceField.

Thanks for the quick reply by the way :)

0
Pavel Pavlov
Telerik team
answered on 18 Nov 2010, 03:03 PM
Hi Miguel Peixoto,

I can see two problems here (both I believe are resolvable )

The first problem - the standard aggregate functions can not be fed with indexed properties.

This is a problem I could easily resolve - either by using a custom aggregate function or  a generic aggregate function.

I will gladly gather a small sample app. for you , however we need to solve one more problem before that :
From your code ( MyTableRow)  I see that the values you are trying to Sum are strings. e.g. column[1] will return a string .

Though we can easily  find a workaround for the indexer problem, I am not sure what to do with the strings .
Numeric aggregates would work only on numeric types. 

Sincerely,
Pavel Pavlov
the Telerik team
Browse the videos here>> to help you get started with RadControls for WPF
0
Miguel Peixoto
Top achievements
Rank 1
answered on 19 Nov 2010, 05:05 PM
Hi Pavel,

Indeed, the MyTableRow has columns defined as ObservableCollection<string>. I didn't find any other way to dinamically represent table values from a XML file (sample below):

<table>
  <tc type="text" lenght="100" precision="0">
    <tr>Standard</tr>
  </tc>
  <tc type="numeric" lenght="11" precision="2">
    <tr>10.000,00</tr>
  </tc>
  <tc type="numeric" lenght="11" precision="2">
    <tr>1.000,00</tr>
  </tc>
  <tc type="text" lenght="50" precision="0">
    <tr>CCCCCC</tr>
  </tc>
  <tc type="date" lenght="0" precision="0">
    <tr>19-11-2010</tr>
  </tc>
  <tc type="bool" lenght="0" precision="0">
    <tr>false</tr>    
  </tc>
</table>

Attribute precision would be used for numeric type format purposes (like DataFormatString or Converter).

Another problem I foresee with this approach is that the SumFunction needs the column identifier for the SourceField. And since my XML tables can be dynamic, there's no straightforward solution to identify a column (at least with the MyTableRow structure).

I would be deeply appreciated if you could help me find a solution, or a better way to represent this XML data as an object that can be assigned as the grid's DataContext.

Thanks in advance !
0
Accepted
Pavel Pavlov
Telerik team
answered on 22 Nov 2010, 03:27 PM
Hello Miguel Peixoto,

When speaking of representation , your approach is OK . However when wee need to perform math on values (e.g. aggregate functions) RadGridView will definitely need to know the type of the data.

This is achievable in many ways but here is an easy one - you can parse the XML and create a DataTable from it . Then you can use that DataTable  as ItemsSource for  the RadGridView. When adding columns to the DataTable you will need to specify the DataType . 

Best wishes,
Pavel Pavlov
the Telerik team
Browse the videos here>> to help you get started with RadControls for WPF
0
Miguel Peixoto
Top achievements
Rank 1
answered on 22 Nov 2010, 06:55 PM
Hi Pavel,

I tried using DataTable instead and now I can get the desired behaviour.

Thanks !
Tags
GridView
Asked by
Miguel Peixoto
Top achievements
Rank 1
Answers by
Pavel Pavlov
Telerik team
Miguel Peixoto
Top achievements
Rank 1
Share this question
or