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

RowDetailsTemplate Binding with Dynamic Data

2 Answers 270 Views
GridView
This is a migrated thread and some comments may be shown as answers.
Marshall
Top achievements
Rank 1
Marshall asked on 07 Dec 2011, 10:30 PM
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 Answers, 1 is accepted

Sort by
0
Tyree
Top achievements
Rank 2
answered on 08 Dec 2011, 12:53 AM
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.
0
Marshall
Top achievements
Rank 1
answered on 08 Dec 2011, 03:45 PM
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.
Tags
GridView
Asked by
Marshall
Top achievements
Rank 1
Answers by
Tyree
Top achievements
Rank 2
Marshall
Top achievements
Rank 1
Share this question
or