Wednesday, 14 November 2012

Telerik WPF RADGrid: How to Horizontally group child rows


I have always endorsed the Telerik UI Controls suite to my clients for the sheer simplicity and flexibility it brings to the table when developing UX intensive applications for desktop or the web alike.

However, though not very amusing to discover, the Telerik Suite does carry a chink ( or two) in its armor and I am today going to help you write a workaround to one of the most commonly faced by the developers.

If you have ever worked with the Telerik WPF RAD grid control and all the things you can do with it, particularly when sorting and filtering child rows to a data-bound parent row , you would expect that it would allow you to display the child rows horizontally as well as the more commonly employed counterpart, the vertical arrangement ( assuming you would also want the various mouse actions like the right-click, double click etc. to work and behave as normal and fire events as normal)

The case is that the RADGrid gets a bit sulky here and does not fare that well when trying to arrange the child rows horizontally instead of vertically, which is, well, more like the natural orientation style of the parent-child grid.

So here is the trick to see how tweaking the underlying XAML gets the job done.

In Child row, switch to the 'RadListbox' control in the RadGridView.RowDetailsTemplate node in the XAML instead and set its orientation to 'horizontal'


Here is the XAML you would see after the tweak:-



<Grid>
        <StackPanel Grid.Column="0">
            <TextBlock Text="Left Menu Area" Margin="4,0,415,0" Height="800" Background="{DynamicResource {x:Static SystemColors.GradientActiveCaptionBrushKey}}"/>
        </StackPanel>
        <StackPanel Grid.Column="1">
            <TextBlock Text="Video Player Area"  Height="800" Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" Margin="103,0,243,0"/>
        </StackPanel>
        <StackPanel Grid.Column="2">
            <telerik:RadGridView x:Name="radGridViewVideo"
                     RowLoaded="radGridViewVideo_RowLoaded_1"
                     LoadingRowDetails="radGridViewVideo_LoadingRowDetails"
                     RowDetailsVisibilityMode="Visible"
                     AutoGenerateColumns="False"
                     ShowGroupPanel="False"
                     IsFilteringAllowed="False"
                     RowIndicatorVisibility="Collapsed"
                     GridLinesVisibility="Horizontal"
                Height="800" Margin="275,0,0,0">
                <telerik:RadGridView.Columns>
                    <telerik:GridViewDataColumn Header="Here is the list of videos you can see !!"
                                  DataMemberBinding="{Binding Name}"
                                  Width="*" />
                </telerik:RadGridView.Columns>
                <telerik:RadGridView.RowDetailsTemplate>
                    <DataTemplate>
                        <StackPanel x:Name="stackPanel">
                            <StackPanel.ContextMenu>
                                <ContextMenu x:Name="mnuDeleteVideo">
                                    <MenuItem Click="MenuItem_Click_1"  CommandParameter="{Binding}" 
                                                              Header="Video -&gt;" InputGestureText="Delete">
                                    </MenuItem>
                                </ContextMenu>
                            </StackPanel.ContextMenu>
                            <telerik:RadListBox x:Name="thumbnailListBox"
                                                SelectionMode="Multiple"
                                                MouseDoubleClick="thumbnailListBox_MouseDoubleClick_1"
                                                ScrollViewer.HorizontalScrollBarVisibility="Auto">
                                <telerik:RadListBox.ItemsPanel>
                                    <ItemsPanelTemplate>
                                        <VirtualizingStackPanel Orientation="Horizontal" Height="100">
                                        </VirtualizingStackPanel>
                                    </ItemsPanelTemplate>
                                </telerik:RadListBox.ItemsPanel>
                            </telerik:RadListBox>
                        </StackPanel>
                    </DataTemplate>
                </telerik:RadGridView.RowDetailsTemplate>
            </telerik:RadGridView>
        </StackPanel>       
    </Grid>


Here is the Code-Behind:




partial class MainWindow : Window
    {
        #region Properties

        public List<Video> Videos { get; set; }

        #endregion

        public MainWindow()
        {
            InitializeComponent();

            this.Videos = Helper.PopulateSampleData();

            this.radGridViewVideo.ItemsSource = this.Videos;
        }

        #region Events

        private void radGridViewVideo_RowLoaded_1(object sender, RowLoadedEventArgs e)
        {
            //This is the parent row load event.
            //Do some business logic here. Like if there is no thumbnail for a video then hide that parent row
        }

        private void radGridViewVideo_LoadingRowDetails(object sender, GridViewRowDetailsEventArgs e)
        {
            int id = ((Video) ((e.DetailsElement).DataContext)).Id;
            Video video = Videos.Find(x => x.Id == id);

            List<string> str = video.Thumbnails;

            string abc = video.Image;

            RadListBox lb = e.DetailsElement.FindName("thumbnailListBox") as RadListBox;

            lb.ItemsSource = str;
        }

        private void thumbnailListBox_MouseDoubleClick_1(object sender, MouseButtonEventArgs e)
        {
            //This is the double click event of the thumbnail item
            //Do some action like launching of player here.
            MessageBox.Show("Double Click");
        }

        #endregion

        private void MenuItem_Click_1(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("Delete Video Clicked");
        }
    }

Here is the Data-Binding Code

public class Video
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public List<string> Thumbnails { get; set; }
        public string Image { get; set; }

        public Video(int id, List<string> images, string img)
        {
            this.Id = id;
            this.Name = string.Format("Video{0}", id);
            this.Thumbnails = images;
            this.Image = img;
        }
    }



Here is the class for Populating test data


public static class Helper
    {
        internal static List<Video> PopulateSampleData()
        {
            var videos = new List<Video>();

            for (int i = 1; i < 4; i++)
            {
                var sample = new List<string>();

                if (i == 1)
                {
                    sample = new List<string>() { "1" };
                }

                if (i == 2)
                {
                    sample = new List<string>() { "1", "2", "3", "4", "5"};
                }

                if (i == 3)
                {
                    sample = new List<string>() { "1", "2", "3" };
                }

                var e = new Video(i, sample, "M9.4136295,2.4576555E-05 C14.800209,-0.013108866 21.555286,5.2417045 22.176739,5.7343717 L22.197632,5.7509871 L22.217262,5.7353773 C22.838715,5.2427092 29.593792,-0.012109431 34.98037,0.0010241366 C35.357132,0.0019429834 35.727203,0.028634096 36.088013,0.084530063 C42.004845,1.0011631 47.504379,6.5009952 42.3377,16.251131 C37.251743,25.848923 27.320799,36.495747 22.4014,37.30304 L22.224001,37.326874 L22.224001,37.333 L22.22303,37.332958 L22.200874,37.329983 L22.170971,37.334 L22.170465,37.325897 L21.992601,37.301998 C17.073202,36.494705 7.1422567,25.847895 2.056303,16.250114 C-3.1103802,6.4999881 2.3891582,1.0001625 8.3059864,0.083530508 C8.6667957,0.027634615 9.0368671,0.00094353169 9.4136295,2.4576555E-05 z");

                videos.Add(e);
            }

            return videos;
        }

    }



And Voila!  It all starts to function:
Here you can see the screen for the test application with the child rows arranged horizontally.






Feel free to drop me a message if this still looks like something you are unable to work out.

No comments:

Post a Comment