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

[Solved] Adapting ASP.NET code to silverlight

6 Answers 133 Views
GridView
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
Jonathan
Top achievements
Rank 1
Jonathan asked on 01 Jul 2011, 01:00 AM
I may be making this too difficult but I'm new to silverlight and asynchronous patterns.  In ASP.NET I use the following code to populate a grid, adding new columns and setting their data as follows:

protected void LoadRates()
        {
            string[] _keys2 = { "ID" };
            grdMemberRates.MasterTableView.DataKeyNames = _keys2;
            _rateSet = BillingOccurrenceManager.GetRateSetByID(Int32.Parse(ddlRateSet.SelectedValue.ToString()));
  
            IQueryable<BillingPeriod> _billingperiods = BillingOccurrenceManager.GetAllBillingPeriodsAsc();
            IQueryable<MemberRateType> _ratetypes = BillingOccurrenceManager.GetAllMemberRateTypes();
              
  
            foreach (BillingPeriod _billingperiod in _billingperiods)
            {
                //GridBoundColumn _col = new GridBoundColumn() { UniqueName = _billingperiod.ID.ToString(), HeaderText = _billingperiod.BillingPeriodMonthYearString };
  
                GridTemplateColumn _col = new GridTemplateColumn() { UniqueName = _billingperiod.ID.ToString(), HeaderText = _billingperiod.BillingPeriodMonthYearString };
                _col.ItemTemplate = new RateTemplate(_billingperiod.ID.ToString());
  
                //highlight the col
                //_col.itemstyle.backcolor = color.whitesmoke;
  
                grdMemberRates.MasterTableView.Columns.Add(_col);
              
            }
              
            grdMemberRates.DataSource = _ratetypes;
            grdMemberRates.DataBind();
        }
  
        protected void grdMemberRates_ItemDataBound(object sender, GridItemEventArgs e)
        {
            if (e.Item is GridDataItem)
            {
                GridDataItem form = (GridDataItem)e.Item;
  
                int rateTypeID = Int32.Parse(e.Item.OwnerTableView.DataKeyValues[e.Item.ItemIndex]["ID"].ToString());
  
                IQueryable<MemberRate> _memberRates = BillingOccurrenceManager.GetMemberRatesForRateSetAndType(_rateSet.ID, rateTypeID);
  
                foreach (MemberRate _memberRate in _memberRates)
                {
                    if (_memberRate.Rate != null)
                       ((TextBox)form[_memberRate.BillingPeriodID.ToString()].FindControl("txt" + _memberRate.BillingPeriodID)).Text = ((decimal)_memberRate.Rate).ToString("N2");
                }
            }
        }


In silverlight I've got the code that builds the grid and creates the columns working but not sure how to populate it with rates.  In ASP.NET I use the ItemDataound event so in Silverlight I thought the rowdatabound event would work well, but in order to load the rates I have to do so asynchronously from the WCF service.  how do I keep the context of the row and set the value of the appropriates cell based on the row data and the column heading?  My Silverlight grid so far  (XAML):

<UserControl x:Class="MemberRatesSL.MainPage"
        mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="600">
    <Grid x:Name="LayoutRoot">
        <StackPanel Orientation="Vertical">
            <telerik:GroupBox Margin="0,5,0,10" telerik:StyleManager.Theme="Windows7" Header="Select the Rate Set (if not default):">
                <telerik:RadComboBox x:Name="cboRateSet" DisplayMemberPath="Description"  Width="200" HorizontalAlignment="Left" telerik:StyleManager.Theme="Windows7" Margin="5"></telerik:RadComboBox>
            </telerik:GroupBox>
            <telerik:RadGridView x:Name="grdMemberRates" SelectionMode="Extended" AutoGenerateColumns="False"  telerik:StyleManager.Theme="Windows7" Height="400" ShowColumnHeaders="True" AlternationCount="2" ShowGroupPanel="False" RowLoaded="grdMemberRates_RowLoaded">
                <telerik:RadGridView.Columns>
                    <telerik:GridViewDataColumn Header="Member Rate Type" DataMemberBinding="{Binding Description}" HeaderTextAlignment="Center" Width="200" IsFilterable="False" IsGroupable="False" IsReorderable="False" ShowDistinctFilters="False" />
                    <telerik:GridViewDataColumn Header="Rate Units" DataMemberBinding="{Binding RateUnits}" HeaderTextAlignment="Center" Width="100" IsFilterable="False" IsGroupable="False" IsReorderable="False" ShowDistinctFilters="False" />
                </telerik:RadGridView.Columns>
            </telerik:RadGridView>
            <telerik:RadButton HorizontalAlignment="Right" x:Name="btnSave" telerik:StyleManager.Theme="Windows7"  Content="Save Changes.." Width="150" Margin="5,5,5,0" Height="30"></telerik:RadButton>
        </StackPanel>
    </Grid>
</UserControl>

And the code behind:

public partial class MainPage : UserControl
{
    ObservableCollection<BillingPeriod> _billingPeriods;
    WCFInterfaceClient _client;
    public MainPage()
    {
        InitializeComponent();
        _client = new WCFInterfaceClient();    
        _client.GetAllMemberRateTypesCompleted += new EventHandler<GetAllMemberRateTypesCompletedEventArgs>(_client_GetAllMemberRateTypesCompleted);
        _client.GetBillingPeriodsCompleted +=new EventHandler<GetBillingPeriodsCompletedEventArgs>(_client_GetBillingPeriodsCompleted);
        _client.GetAllRateSetsCompleted += new EventHandler<GetAllRateSetsCompletedEventArgs>(_client_GetAllRateSetsCompleted);
        _client.GetMemberRatesForRateSetAndTypeCompleted += new EventHandler<GetMemberRatesForRateSetAndTypeCompletedEventArgs>(_client_GetMemberRatesForRateSetAndTypeCompleted);
        try
        {
            _client.GetAllRateSetsAsync();
        }
        catch (Exception ex)
        {
            _client.CloseAsync();
        }
    }
    void _client_GetAllRateSetsCompleted(object sender, GetAllRateSetsCompletedEventArgs e)
    {
        cboRateSet.ItemsSource = e.Result;
        cboRateSet.SelectedIndex = 0;
        _client.GetBillingPeriodsAsync();
    }
    void _client_GetAllMemberRateTypesCompleted(object sender, GetAllMemberRateTypesCompletedEventArgs e)
    {
        ObservableCollection<MemberRateType> _memberRates = e.Result;
        grdMemberRates.ItemsSource = _memberRates;
    }
    void _client_GetBillingPeriodsCompleted(object sender, GetBillingPeriodsCompletedEventArgs e)
    {
        _billingPeriods = e.Result;
        foreach (BillingPeriod _billingPeriod in _billingPeriods)
        {
            grdMemberRates.Columns.Add(new GridViewDataColumn() { Header = DateTimeHelper.GetMonthName(_billingPeriod.Month, false) + " " + _billingPeriod.Year, UniqueName="BillingPeriod" + _billingPeriod.ID });
        }
        _client.GetAllMemberRateTypesAsync();
    }
    private void grdMemberRates_RowLoaded(object sender, Telerik.Windows.Controls.GridView.RowLoadedEventArgs e)
    {
        bool isDetailRow = !(e.Row is GridViewNewRow || e.Row is GridViewHeaderRow || e.Row is GridViewFooterRow);
        if (isDetailRow)
        
            //load the 
            MemberRateType _memberRateType = e.DataElement as MemberRateType;
            //load the rates asynch...  How do I load the data into the row if I have to catch the asynch return?
            _client.GetMemberRatesForRateSetAndTypeAsync(Int32.Parse(cboRateSet.SelectedValue.ToString()), _memberRateType.ID);
        }
    }
    void _client_GetMemberRatesForRateSetAndTypeCompleted(object sender, GetMemberRatesForRateSetAndTypeCompletedEventArgs e)
    {
        //??? How do I load the data into the row if I have to catch the asynch return, how to I hold the row context do I cursor through the rows looking at the ID's
    }
}

Thanks very much let me know if you need  a screenshot to understand the issue...

Jonathan

6 Answers, 1 is accepted

Sort by
0
Jonathan
Top achievements
Rank 1
answered on 01 Jul 2011, 03:30 AM
OK so I decided that spawning asynchronous calls from each rowloaded event was unmanageable.  I changed the silverlight Main class to look like:

public partial class MainPage : UserControl
    {
        ObservableCollection<BillingPeriod> _billingPeriods;
        ObservableCollection<MemberRate> _rates;
        WCFInterfaceClient _client;
  
        public MainPage()
        {
            InitializeComponent();
  
            _client = new WCFInterfaceClient();    
            _client.GetAllMemberRateTypesCompleted += new EventHandler<GetAllMemberRateTypesCompletedEventArgs>(_client_GetAllMemberRateTypesCompleted);
            _client.GetBillingPeriodsCompleted +=new EventHandler<GetBillingPeriodsCompletedEventArgs>(_client_GetBillingPeriodsCompleted);
            _client.GetAllRateSetsCompleted += new EventHandler<GetAllRateSetsCompletedEventArgs>(_client_GetAllRateSetsCompleted);
            _client.GetMemberRatesForRateSetCompleted += new EventHandler<GetMemberRatesForRateSetCompletedEventArgs>(_client_GetMemberRatesForRateSetCompleted);
  
            try
            {
                _client.GetAllRateSetsAsync();
            }
            catch (Exception ex)
            {
                _client.CloseAsync();
            }
        }
  
        void _client_GetAllRateSetsCompleted(object sender, GetAllRateSetsCompletedEventArgs e)
        {
            cboRateSet.ItemsSource = e.Result;
            cboRateSet.SelectedIndex = 0;
            _client.GetBillingPeriodsAsync();
        }
  
        void _client_GetAllMemberRateTypesCompleted(object sender, GetAllMemberRateTypesCompletedEventArgs e)
        {
            ObservableCollection<MemberRateType> _memberRates = e.Result;
            grdMemberRates.ItemsSource = _memberRates;
            _client.GetMemberRatesForRateSetAsync(((RateSet)cboRateSet.SelectedValue).ID);
        }
  
        void _client_GetBillingPeriodsCompleted(object sender, GetBillingPeriodsCompletedEventArgs e)
        {
            _billingPeriods = e.Result;
            foreach (BillingPeriod _billingPeriod in _billingPeriods)
            {
                grdMemberRates.Columns.Add(new GridViewColumn() { Header = DateTimeHelper.GetMonthName(_billingPeriod.Month, false) + " " + _billingPeriod.Year, UniqueName="BillingPeriod" + _billingPeriod.ID });
            }
            _client.GetAllMemberRateTypesAsync();
        }
  
        //private void grdMemberRates_RowLoaded(object sender, Telerik.Windows.Controls.GridView.RowLoadedEventArgs e)
        //{
        //    bool isDetailRow = !(e.Row is GridViewNewRow || e.Row is GridViewHeaderRow || e.Row is GridViewFooterRow);
        //    if (isDetailRow)
        //    {
        //        //load the 
        //        MemberRateType _memberRateType = e.DataElement as MemberRateType;
        //        //load the rates asynch...  How do I load the data into the row if I have to catch the asynch return?
        //        _client.GetMemberRatesForRateSetAsync(((RateSet)cboRateSet.SelectedValue).ID, _memberRateType.ID);
        //    }
        //}
  
        void _client_GetMemberRatesForRateSetCompleted(object sender, GetMemberRatesForRateSetCompletedEventArgs e)
        {
            _rates = e.Result;
  
            //loop through the rows
            foreach (object item in grdMemberRates.Items)
            {
                int _memberRateTypeID = ((MemberRateType)item).ID;
  
                GridViewRow row = grdMemberRates.ItemContainerGenerator.ContainerFromItem(item) as GridViewRow;
  
                if (row != null)
                {
                    foreach (MemberRate _rate in _rates)
                    {
                        if (_rate.MemberRateTypeID == _memberRateTypeID)
                        {
                            GridViewCellBase cell = (from c in row.Cells
                                                     where c.Column.UniqueName == "BillingPeriod" + _rate.BillingPeriodID
                                                     select c).FirstOrDefault();
                            if (cell != null)
                            {
                                cell.Content = _rate.Rate;
                            }
                        }
                    }
                }
            }
        }

The rates now show in the correct columns,  EXCEPT for if those columns are not currently visible due to being "off screen" in the scrolled part of the radgrid.  when I scrooll over to those columns and then scroll back the content is lost.  Why is this?

Can you recommend an approach where you convert a one-dimensional array of database columns into a two dimesional grid as I am trying to do.  basiclly the vertical axis is rate type, the horizontal axis is billing period the records are in ID, BillingPeriodID, RateTypeID, Rate format....  Some billing periods and rate types may not be represented int the rateset.  Not sure what to do next.  Should I build an XML document and bind to that rather than building columns based on a list of billing periods...  ANy help appreciated.

Thanks
Jonathan
0
Jonathan
Top achievements
Rank 1
answered on 01 Jul 2011, 03:58 AM
OK I got around the scrolling problem by turning off the scrolling on the radgridview and adding a new scrollviewer that wraps the radgridview.  However, when I go to edit a cell by clicking on it it goes blank and stays blank...  I am sure that I am jsut approaching this wrong.  Would building a datatable and then binding the gridview to the datatable be better than adding the gridviewrows by hand?

 

 

 

 

<ScrollViewer VerticalScrollBarVisibility="Hidden" HorizontalScrollBarVisibility="Visible">
                <telerik:RadGridView x:Name="grdMemberRates" ScrollViewer.HorizontalScrollBarVisibility="Hidden"  ScrollViewer.VerticalScrollBarVisibility="Hidden" SelectionMode="Extended" AutoGenerateColumns="False"  telerik:StyleManager.Theme="Windows7" Height="400" ShowColumnHeaders="True" AlternationCount="2" ShowGroupPanel="False">
                <telerik:RadGridView.Columns>
                    <telerik:GridViewDataColumn Header="Member Rate Type" DataMemberBinding="{Binding Description}" HeaderTextAlignment="Center" Width="200" IsFilterable="False" IsGroupable="False" IsReorderable="False" ShowDistinctFilters="False" />
                    <telerik:GridViewDataColumn Header="Rate Units" DataMemberBinding="{Binding RateUnits}" HeaderTextAlignment="Center" Width="100" IsFilterable="False" IsGroupable="False" IsReorderable="False" ShowDistinctFilters="False" />
                </telerik:RadGridView.Columns>
            </telerik:RadGridView>
            </ScrollViewer>



Jonathan

0
Jonathan
Top achievements
Rank 1
answered on 01 Jul 2011, 03:59 AM
Attached is a pic of what I am trying to do.  The end goal is to be able to cut and paste from excel into the rate cells....
0
Milan
Telerik team
answered on 01 Jul 2011, 07:39 AM
Hi Jonathan,

You shouldn't be creating GridViewRows and GridViewCells manually - they are created by the grid when the grid is bound. Please refer to our demos and help documentation for more information about binding, editing, copy/paste, etc. 


Best wishes,
Milan
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
0
Jonathan
Top achievements
Rank 1
answered on 01 Jul 2011, 09:03 AM
Hi Milan,

I know how to bind lists to a grid, the issue I was trying to solve is the transpose of the two dimensional matrix.  I did find a good source of a solution that I can use:

http://blogs.telerik.com/blogs/posts/09-04-23/lightweight_datatable_for_your_silverlight_applications.aspx

Thanks,
Jonathan
0
Jonathan
Top achievements
Rank 1
answered on 11 Jul 2011, 10:35 PM
Here is the solution :-)
        void _client_GetMemberRatesForRateSetCompleted(object sender, GetMemberRatesForRateSetCompletedEventArgs e)
        {
            //build a datatable
            _rates = e.Result;
  
            _table = new DataTable();
  
            _table.Columns.Add(new DataColumn() { ColumnName = "ID", DataType = typeof(int) });
            _table.Columns.Add(new DataColumn() { ColumnName = "Description", DataType = typeof(string) });
            _table.Columns.Add(new DataColumn() { ColumnName = "RateUnits", DataType = typeof(string) });
              
            foreach (BillingPeriod _billingPeriod in _billingPeriods)
            {
                _table.Columns.Add(new DataColumn() { ColumnName="BillingPeriod" + _billingPeriod.ID, DataType=typeof(decimal) });
                grdMemberRates.Columns.Add(new GridViewDataColumn() { IsFilterable=false, Header = DateTimeHelper.GetMonthName(_billingPeriod.Month, false) + " " + _billingPeriod.Year, UniqueName = _billingPeriod.ID.ToString(), DataMemberBinding = new Binding("BillingPeriod" + _billingPeriod.ID) });
            }
  
            try
            {
                foreach (MemberRateType _type in _memberRateTypes)
                {
                    DataRow _row = new DataRow(_table);
                      
                    _row["ID"] = _type.ID;
                    _row["Description"] = _type.Description;
                    _row["RateUnits"] = _type.RateUnits;
  
                    foreach (MemberRate _rate in _rates)
                    {
                        if (_rate.MemberRateTypeID == _type.ID)
                        {
                            _row["BillingPeriod" + _rate.BillingPeriodID] = _rate.Rate;
                        }
                    }
                    _table.Rows.Add(_row);
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.ToString());
            }
  
            grdMemberRates.ItemsSource = _table;
}
Tags
GridView
Asked by
Jonathan
Top achievements
Rank 1
Answers by
Jonathan
Top achievements
Rank 1
Milan
Telerik team
Share this question
or