RowDetailsTemplate Binding with Dynamic Data

3 posts, 0 answers
  1. Marshall
    Marshall avatar
    4 posts
    Member since:
    Aug 2012

    Posted 07 Dec 2011 Link to this post

    Hello,
    I'm running into a problem when trying to bind data to the RowDetailsTemplate.  Specifically my RadGridView ItemsSource is an ObservableCollection<DataRow> based off of the http://demos.telerik.com/silverlight/#GridView/DataSources example.  The DataRows contain additional data that I want to bind to the RowDetail.  Is this even possible?  Below is my code (only three files needed plus the required Telerik references: Controls, Controls.GridView, Controls.Input, and Data).

    Thanks for any help!

    <UserControl x:Class="SilverlightGridViewBinding.MainPage"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                 xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
                 mc:Ignorable="d"
                 d:DesignHeight="300" d:DesignWidth="400">
     
        <Grid x:Name="LayoutRoot" Background="White">
            <telerik:RadGridView x:Name="RadGrid"
                                 AutoGenerateColumns="False"
                                 ItemsSource="{Binding Data}"
                                 ShowGroupPanel="False"
                                 CanUserReorderColumns="False"
                                 CanUserSortColumns="False"
                                 CanUserResizeColumns="False"
                                 CanUserFreezeColumns="False"
                                 IsReadOnly="True"
                                 RowIndicatorVisibility="Collapsed"
                                 IsFilteringAllowed="False"
                                 AlternateRowBackground="#FFE6EDFA"
                                 AlternationCount="2">
                <telerik:RadGridView.Columns>
                    <telerik:GridViewToggleRowDetailsColumn />
                </telerik:RadGridView.Columns>
                <telerik:RadGridView.RowDetailsTemplate>
                    <DataTemplate>
                        <Grid Background="White">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition />
                                <ColumnDefinition />
                            </Grid.ColumnDefinitions>
                            <Grid.RowDefinitions>
                                <RowDefinition />
                                <RowDefinition />
                            </Grid.RowDefinitions>
     
                            <TextBlock Text="Address:" />
                            <!-- Binding to Address and Email doesn't work. 
                                 How do you bind the RowDetailsTemplate controls when
                                 your RadGridView ItemsSource is dynamic (i.e.
                                 an ObservableCollection<DataRow>)? -->
                            <TextBlock Grid.Column="1" Text="{Binding Address}" />
                            <TextBlock Grid.Row="1" Text="Email:" />
                            <TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Email}" />
     
                        </Grid>
                    </DataTemplate>
                </telerik:RadGridView.RowDetailsTemplate>
            </telerik:RadGridView>
        </Grid>
    </UserControl>

    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using Telerik.Windows.Controls;
     
    namespace SilverlightGridViewBinding
    {
        public partial class MainPage : UserControl, INotifyPropertyChanged
        {
            private ObservableCollection<DataRow> _data;
     
            public MainPage()
            {
                InitializeComponent();
                DataContext = this;
     
                Loaded += MainPage_Loaded;
            }
     
            void MainPage_Loaded(object sender, RoutedEventArgs e)
            {
                GetColumns();
            }
     
            /// <summary>
            /// GetColumns creates GridViewDataColumns dynamically
            /// </summary>
            private void GetColumns()
            {
                var columns = new Dictionary<string, string> { { "UserName", "User Name" }, { "CompanyName", "Company Name" }, { "Id", "Your Id" } };
     
                foreach (KeyValuePair<string, string> kvp in columns)
                {
                    var gridViewDataColumn = new GridViewDataColumn
                    {
                        DataMemberBinding = new Binding(kvp.Key),
                        Header = kvp.Value
                    };
     
                    RadGrid.Columns.Add(gridViewDataColumn);
                }
            }
     
            /// <summary>
            /// GetData provides the data for the grid and additional data for the detail record
            /// </summary>
            /// <returns></returns>
            private ObservableCollection<DataRow> GetData()
            {
                var data = new ObservableCollection<DataRow>();
     
                for (var i = 0; i < 3; i++ )
                {
                    var row = new DataRow();
     
                    row["UserName"] = string.Format("User Name {0}", i);
                    row["CompanyName"] = string.Format("Company Name {0}", i);
                    row["Id"] = string.Format("{0}", i);
                    // Add more data to each row than we want to display in the grid
                    // This data will hopefully be displayed in the row detail
                    row["Address"] = string.Format("Address {0}", i);
                    row["Email"] = string.Format("Email {0}", i);
     
                    data.Add(row);
                }
     
                return data;
            }
     
            public ObservableCollection<DataRow> Data
            {
                get { return _data ?? (_data = GetData()); }
            }
     
            public event PropertyChangedEventHandler PropertyChanged;
     
            public void OnPropertyChanged(string property)
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(property));
                }
            }
        }
    }

    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Dynamic;
     
    namespace SilverlightGridViewBinding
    {
        /// <summary>
        /// This class was copied from Telerik.Windows.Examples.GridView.DataSources.
        /// </summary>
        public class DataRow : DynamicObject, INotifyPropertyChanged
        {
            IDictionary<string, object> _data;
     
            public DataRow()
            {
                _data = new Dictionary<string, object>();
            }
     
            public DataRow(IDictionary<string, object> source)
            {
                _data = source;
            }
             
            public override IEnumerable<string> GetDynamicMemberNames()
            {
                return _data.Keys;
            }
     
            public override bool TryGetMember(GetMemberBinder binder, out object result)
            {
                result = this[binder.Name];
     
                return true;
            }
     
            public override bool TrySetMember(SetMemberBinder binder, object value)
            {
                this[binder.Name] = value;
     
                return true;
            }
     
            public object this[string columnName]
            {
                get
                {
                    if (_data.ContainsKey(columnName))
                    {
                        return _data[columnName];
                    }
     
                    return null;
                }
                set
                {
                    if (!_data.ContainsKey(columnName))
                    {
                        _data.Add(columnName, value);
     
                        OnPropertyChanged(columnName);
                    }
                    else
                    {
                        if (_data[columnName] != value)
                        {
                            _data[columnName] = value;
     
                            OnPropertyChanged(columnName);
                        }
                    }
                }
            }
     
            private void OnPropertyChanged(string propertyName)
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                }
            }
     
            #region INotifyPropertyChanged Members
     
            public event PropertyChangedEventHandler PropertyChanged;
     
            #endregion
     
        }
    }

  2. Tyree
    Tyree avatar
    105 posts
    Member since:
    Dec 2006

    Posted 07 Dec 2011 Link to this post

    I have not tried it with a DynamicObject but binding can work with a dictionary so if all else failed you may be able to expose your _data and try binding to an index.

    What are your binding errors when doing the Address and Email? If its not showing in the grid then you are getting errors, those might give some clues.
  3. DevCraft banner
  4. Marshall
    Marshall avatar
    4 posts
    Member since:
    Aug 2012

    Posted 08 Dec 2011 Link to this post

    Thanks for the suggestion.  I'll try exposing _data.  I'm not sure though what the binding syntax would be once _data is exposed.

     I found another possible solution which is to use a Converter.  It seems promising.

    <TextBlock Grid.Column="1" Text="{Binding Converter={StaticResource DataConverter}, ConverterParameter=Address}" />

    So in the Convert method of my DataConverter I can access Address in the value object which is, in my case, a DataRow.  This will work.  I guess I was hoping to figure out a better binding syntax to use in the xaml instead of using a Converter.

    Thanks again.
Back to Top