UserControl inside RadPanelBarItem

12 posts, 0 answers
  1. Carlos
    Carlos avatar
    6 posts
    Member since:
    Jan 2011

    Posted 17 Feb 2011 Link to this post

    Hey there,
    I'm trying to databind a usercontrol that has a RadPanelBarControl, with two RadPanelBarItems, and these two PanelBarItems have other usercontrols inside.

    When i databind the datacontext of the main usercontrol for the first time, the RadPanelBar shows the content correctly, but when i change the datacontext, it doesnt refresh its layout...

    I've tried to reproduce exactly the same but with RadTabControls, and it works perfectly.


    This is how i change the datacontext of the usercontrol in my host page.xml:

    CategoryViewModel vm = new CategoryViewModel(c.DataObject.idCategory);
    categoryDetailControl.LayoutRoot.DataContext = vm;


    The usercontrol XAML:

    <UserControl x:Class="CTI2.Client.Silverlight.Controls.CategoryDetail"
        xmlns:viewModels="clr-namespace:CTI2.Client.Silverlight.ViewModels"
        xmlns:local="clr-namespace:CTI2.Client.Silverlight.Controls"
        mc:Ignorable="d"
        d:DesignHeight="300" d:DesignWidth="800">
          
        <Grid x:Name="LayoutRoot" Background="White">
            <telerik:RadPanelBar ExpandMode="Multiple" Orientation="Vertical" ScrollViewer.HorizontalScrollBarVisibility="Disabled"
                                 VerticalAlignment="Stretch" VerticalContentAlignment="Stretch"
                                 HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch">
                <telerik:RadPanelBarItem Header="Sub-Categorias (Capas agregadoras)">
                    <TextBlock Text="Ainda não disponível nesta versão..." FontWeight="Bold" FontSize="12" FontStyle="Italic" />
                </telerik:RadPanelBarItem>
                <telerik:RadPanelBarItem Header="Titulos na Categoria" >
                    <local:CategorySushi x:Name="categorySushiControl" />
                </telerik:RadPanelBarItem>
            </telerik:RadPanelBar>
        </Grid>
    </UserControl>
  2. Tina Stancheva
    Admin
    Tina Stancheva avatar
    3298 posts

    Posted 22 Feb 2011 Link to this post

    Hi Carlos,

    From the code snippet you sent I am not sure how should the changed DataContext reflect the UserControl's layout since I cannot see any Bindings in the xaml. Perhaps I am missing something, so could you please elaborate a bit more or send us the code-behind and the ViewModels as well.

    Also, you can have a look at this or this article illustrating how to data bind the RadPaneBar.

    Best wishes,
    Tina Stancheva
    the Telerik team
    Registration for Q1 2011 What’s New Webinar Week is now open. Mark your calendar for the week starting March 21st and book your seat for a walk through all the exciting stuff we ship with the new release!
  3. DevCraft banner
  4. Carlos
    Carlos avatar
    6 posts
    Member since:
    Jan 2011

    Posted 22 Feb 2011 Link to this post

    Thanks for the response,
    I'll try to elaborate.

    Suppose you have a master-detail type page, where in the left side you have a treeview and on the right side, you have the detail of the item you select in the treeview.

    The usercontrol i posted above is the detail part.

    When i click on an item in the treeview, I create an instance of the ViewModel and set some properties on it. Then i assign it.
    I use the Telerik's treeview OnSelected eventhandler to do it:

    void tvCategories_Selected(object sender, Telerik.Windows.RadRoutedEventArgs e)
            {
                RadTreeViewItem item = e.OriginalSource as RadTreeViewItem;
                currentItem = item;
     
                CategoriesModel c = currentItem.Item as CategoriesModel;
     
                CategoryViewModel vm = new CategoryViewModel(c.DataObject.idCategory);
                categoryDetailControl.DataContext = vm;
            }

    (categoryDetailControl is the UserControl i posted above)

    The CategoryViewModel class begins a load operation when i create it with constructor parameters. What it does is to fetch detailed category information based on the CategoryId.

    Now the problem is that the RadPanelBar doesnt show anything at all. The binding simply doesnt happen. Most of my bindings are setted up on the usercontrol that is inside of the 2nd RadPanelBarItem. That usercontrol (local:categorySushi) it is just a simple EditForm with some textboxes on it, and nothing is done via codebehind.

    I know that my EditForm is OK because if use a RadExpander instead of the RadPanelBar everything works OK.

    Maybe the RadPanelBar is not the best control for this particular case, i just want to use it as a accordion container (like a StackPanel that has cool background and a colapse/expand ability). I dont want to create RadPanelBarItems dynamically nor databind it. I just want to databind the items that it contains.

    Thanks,
    Carlos
  5. Tina Stancheva
    Admin
    Tina Stancheva avatar
    3298 posts

    Posted 25 Feb 2011 Link to this post

    Hello Carlos,

    Unfortunately the RadPanelBar cannot be used in this scenario, since in order to databind its content you need to databind its/its items ItemsSource, which won't work in your case.

    Therefore it is better to use the RadExpander instead. You can even handle the RadExpander's Collapsed() and Expanded() events to create a composite UserControl, containing multiple Expanders that behave like an accordion. You can even edit the ControlTemplate of the RadExpander in order to modify it style to look more like the RadPanelBar style for example.

    I attached a sample project illustrating similar scenario. I hope it helps.

    Regards,
    Tina Stancheva
    the Telerik team
    Registration for Q1 2011 What’s New Webinar Week is now open. Mark your calendar for the week starting March 21st and book your seat for a walk through all the exciting stuff we ship with the new release!
  6. Bala
    Bala avatar
    20 posts
    Member since:
    Dec 2011

    Posted 30 Jan 2013 Link to this post

    Hello Tina Stancheva,
       
            How will you retrieve the user control    inside the Expander?

    Regards,
    bala
  7. Tina Stancheva
    Admin
    Tina Stancheva avatar
    3298 posts

    Posted 31 Jan 2013 Link to this post

    Hi Bala,

    The RadExpander.Content property can give you access to all UIElements hosted in the content part of the control. Let me know if that helps.

    Regards,
    Tina Stancheva
    the Telerik team

    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

  8. Bala
    Bala avatar
    20 posts
    Member since:
    Dec 2011

    Posted 16 Feb 2013 Link to this post

    Hello Tina Stancheva,
     
    Yes, I got resolved. Thank you for your kind information. But is there any option with RadPanelBar 
      to access the user Control placed in  RadPanelBarItems.?

    With regards,
    Bala 
  9. Tina Stancheva
    Admin
    Tina Stancheva avatar
    3298 posts

    Posted 18 Feb 2013 Link to this post

    Hello Bala,

    The RadPanelBar control displays hierarchical data. This means that the RadPanelBarItem control exposes both Items and ItemsSource properties which you can use to get the collection of children displayed inside each RadPanelBarItem.

    You can examine this tutorial that demonstrates how to bind the RadPanelBar to a hierarchical data as it can give you better understanding of the PanelBarItems structure.

    Regards,
    Tina Stancheva
    the Telerik team

    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

  10. Graeme
    Graeme avatar
    21 posts
    Member since:
    May 2012

    Posted 05 Mar 2014 in reply to Bala Link to this post

    I was looking for a similar solution as I need to dynamically add Panels to the RadPanelBar control with each Panel having a different UserControl injected. I've found that MEF makes it possible. Here's how I did it:

    1. Create a UIProvider class to point to the control:

    01.<ExportUIFilterViewProvider("PanelBar.UIProvider")>
    02.Public Class UIProvider : Inherits UIProviderBase
    03. 
    04.    Public Overrides ReadOnly Property Title() As String
    05.        Get
    06.            Return "Panel Header goes here"
    07.        End Get
    08.    End Property
    09. 
    10.    <Import(UsercontrolView)>
    11.    Public Overrides Property EntryPage() As ExportFactory(Of IUIPanelProviderView)
    12. 
    13.End Class

    2. Implement the IUIPanelProviderView interface on the Usercontrol and Export the UsercontrolView to match the import.

    3. Now in your viewmodel (behind the PanelBar control) import all the "PanelBar.UIProvider" wrappers and wrap them in a HierarchicalData class:

    01.#Region "Plug-in Management"
    02. 
    03.    <ImportMany("PanelBar.UIProvider", AllowRecomposition:=True)>
    04.    Public Property Plugins() As UIProviderBase()
    05. 
    06.    Public Sub OnImportsSatisfied() Implements System.ComponentModel.Composition.IPartImportsSatisfiedNotification.OnImportsSatisfied
    07. 
    08.        For Each plugin As UIProviderBase In Plugins
    09.            Items.Add(New PanelItemData With {.Header = plugin.Title, .Contents = New ObservableCollection(Of UIFilterViewProviderBase) From {plugin}})
    10.        Next
    11. 
    12.    End Sub
    13. 
    14.#End Region

    1.Friend Class PanelItemData
    2.    Property Header As String
    3.    Property Contents As ObservableCollection(Of UIFilterViewProviderBase)
    4.End Class

    4. Here's the Xaml for the PanelBar control:

    01.<UserControl.Resources>
    02.    <converters:UIProviderToFilterControlConverter x:Key="UIProviderToFilterControlConverter"/>
    03.     
    04.    <DataTemplate x:Key="ContentTemplate">
    05.        <ContentControl Content="{Binding EntryPage, Converter={StaticResource UIProviderToFilterControlConverter}}" />
    06.    </DataTemplate>
    07.</UserControl.Resources>
    08. 
    09.<Grid x:Name="LayoutRoot">
    10.    <telerik:RadPanelBar ItemsSource="{Binding Items}">
    11.        <telerik:RadPanelBar.ItemTemplate>
    12.            <telerik:HierarchicalDataTemplate ItemsSource="{Binding Contents}" ItemTemplate="{StaticResource ContentTemplate}">
    13.                <Grid VerticalAlignment="Center" >
    14.                    <TextBlock Text="{Binding Header}" />
    15.                </Grid>
    16.            </telerik:HierarchicalDataTemplate>
    17.        </telerik:RadPanelBar.ItemTemplate>
    18.    </telerik:RadPanelBar>
    19.</Grid>

    5. Finally, the Converter class to inject the control:
     
    01.Public Class UIProviderToFilterControlConverter : Implements IValueConverter
    02. 
    03.    Public Function Convertvalue As Object,
    04.                            targetType As System.Type,
    05.                            parameter As Object,
    06.                            culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.Convert
    07.        Return DirectCast(value, ExportFactory(Of IFilterView)).CreateExport.Value
    08. 
    09.    End Function
    10. 
    11.    Public Function ConvertBackvalue As Object,
    12.                                targetType As System.Type,
    13.                                parameter As Object,
    14.                                culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.ConvertBack
    15.        Throw New NotSupportedException
    16.    End Function
    17. 
    18.End Class


    It's after 3am here ... so in the morning, if I have time, I'll try and put together a sample and uploaded it.

    Otherwise, enjoy!

    Graeme

  11. Graeme
    Graeme avatar
    21 posts
    Member since:
    May 2012

    Posted 05 Mar 2014 in reply to Graeme Link to this post

    Small Adjustment to the viewmodel. Left out the following:

    1.Public Property Items As New ObservableCollection(Of PanelItemData)

    From:

    01.#Region "Plug-in Management"
    02. 
    03.    <ImportMany("PanelBar.UIProvider", AllowRecomposition:=True)>
    04.    Public Property Plugins() As UIProviderBase()
    05. 
    06.    Public Sub OnImportsSatisfied() Implements System.ComponentModel.Composition.IPartImportsSatisfiedNotification.OnImportsSatisfied
    07. 
    08.        For Each plugin As UIProviderBase In Plugins
    09.            Items.Add(New PanelItemData With {.Header = plugin.Title, .Contents = New ObservableCollection(Of UIFilterViewProviderBase) From {plugin}})
    10.        Next
    11. 
    12.    End Sub
    13. 
    14.#End Region

    1.Friend Class PanelItemData
    2.    Property Header As String
    3.    Property Contents As ObservableCollection(Of UIFilterViewProviderBase)
    4.End Class

    4. Here's the Xaml for the PanelBar control:

    01.<UserControl.Resources>
    02.    <converters:UIProviderToFilterControlConverter x:Key="UIProviderToFilterControlConverter"/>
    03.     
    04.    <DataTemplate x:Key="ContentTemplate">
    05.        <ContentControl Content="{Binding EntryPage, Converter={StaticResource UIProviderToFilterControlConverter}}" />
    06.    </DataTemplate>
    07.</UserControl.Resources>
    08. 
    09.<Grid x:Name="LayoutRoot">
    10.    <telerik:RadPanelBar ItemsSource="{Binding Items}">
    11.        <telerik:RadPanelBar.ItemTemplate>
    12.            <telerik:HierarchicalDataTemplate ItemsSource="{Binding Contents}" ItemTemplate="{StaticResource ContentTemplate}">
    13.                <Grid VerticalAlignment="Center" >
    14.                    <TextBlock Text="{Binding Header}" />
    15.                </Grid>
    16.            </telerik:HierarchicalDataTemplate>
    17.        </telerik:RadPanelBar.ItemTemplate>
    18.    </telerik:RadPanelBar>
    19.</Grid>

    5. Finally, the Converter class to inject the control:
     
    01.Public Class UIProviderToFilterControlConverter : Implements IValueConverter
    02. 
    03.    Public Function Convertvalue As Object,
    04.                            targetType As System.Type,
    05.                            parameter As Object,
    06.                            culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.Convert
    07.        Return DirectCast(value, ExportFactory(Of IFilterView)).CreateExport.Value
    08. 
    09.    End Function
    10. 
    11.    Public Function ConvertBackvalue As Object,
    12.                                targetType As System.Type,
    13.                                parameter As Object,
    14.                                culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.ConvertBack
    15.        Throw New NotSupportedException
    16.    End Function
    17. 
    18.End Class


    It's after 3am here ... so in the morning, if I have time, I'll try and put together a sample and uploaded it.

    Otherwise, enjoy!

    Graeme

  12. Graeme
    Graeme avatar
    21 posts
    Member since:
    May 2012

    Posted 05 Mar 2014 in reply to Graeme Link to this post

    I've broken out the code from our main app into a demo app - DynamicLoadRadPanelBar.zip . This will demonstrate how to dynamically load the RadPanelBar control Panes with UserControls at runtime using MVVM with MEF. This method is pretty universal and can be used elsewhere. :)

    Enjoy!
  13. Tina Stancheva
    Admin
    Tina Stancheva avatar
    3298 posts

    Posted 10 Mar 2014 Link to this post

    Hi Graeme,

    Thank you for sharing your solution with the community. I updated your Telerik points for your involvement.

    Regards,
    Tina Stancheva
    Telerik

    DevCraft Q1'14 is here! Watch the online conference to see how this release solves your top-5 .NET challenges. Watch on demand now.

Back to Top
DevCraft banner