Media Center like menu

4 posts, 0 answers
  1. Phillip
    Phillip avatar
    2 posts
    Member since:
    Jun 2008

    Posted 17 Dec 2010 Link to this post

    Hi,
    I am using the carousel control to implement a media center like menu for my application. The main menu items should scroll vertically with the current item in the centre and the sub items should then appear below it and be chooseable. The priority is on easy keyboard navigation.

    The problems I am facing are:

    1) Styling the carousel seems to be incredibly difficult. Just having the main menu item description with a list of sub items is even difficult to do. Adding additional elements to the data template seems to stop the sub items from rendering.

    2) Keyboard navigation does not work correctly. I'd like the main menu to scroll on Up / Down and the sub menu to scroll on Left / Right. Unfortunately, only the currently focused carousel panel will scroll and it then scrolls on all arrow key presses.

    The control seems to have such a steep learning curve that I'm tempted to ditch it and write my own custom control - albeit without some of the nice scrolling effects that your control brings.

    I've attached my attempt below, it is based on a sample I saw on this site. Any help would be appreciated.

        <UserControl.Resources>
            <Path
              x:Key="horizontalPath"
              Stretch="None"
              Opacity="1"
              Data="M0,0 C0,0 0,800 0,800"
              Stroke="#FFB4B4B4"
              StrokeThickness="4">
            </Path>
            <DataTemplate DataType="{x:Type local:Message}">
                    <telerik:CarouselScrollViewer CanContentScroll="True" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden">
    <!-- putting in a header here stops the child panel from rendering correctly -->
                        <telerik:RadCarouselPanel Loaded="RadCarouselPanel_Loaded" CanVerticallyScroll="False" TopContainerChanged="RadCarouselPanel_TopContainerChanged_1">
                            <Button Content="menu1"/>
                            <Button Content="menu2"/>
                            <Button Content="menu3"/>
                            <Button Content="menu4"/>
                            <Button Content="menu5"/>
                            <Button Content="menu6"/>
                        </telerik:RadCarouselPanel>
                </telerik:CarouselScrollViewer>
            </DataTemplate>
            <Style TargetType="{x:Type telerik:CarouselItem}">
                <Setter Property="MaxHeight" Value="1000"/>
                <Setter Property="MaxWidth" Value="1000"/>
                <Setter Property="Height" Value="200"/>
                <Setter Property="Width" Value="400"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="telerik:CarouselItem">
                            <Border x:Name="mainBorder">
                                <Border Opacity="1" BorderBrush="#3F000000" BorderThickness="1,1,1,1" CornerRadius="5,5,5,5" Margin="10,10,10,10" x:Name="CarouselItemInnerBorder" SnapsToDevicePixels="True">
                                    <Border.Background>
                                        <LinearGradientBrush EndPoint="101,462" StartPoint="101,13" MappingMode="Absolute">
                                            <GradientStop Color="#FF2C3A68" Offset="0"/>
                                            <GradientStop Color="#FF000000" Offset="1"/>
                                            <GradientStop Color="#FF0F224C" Offset="0.045"/>
                                            <GradientStop Color="#FF000000" Offset="0.0451"/>
                                        </LinearGradientBrush>
                                    </Border.Background>
                                    <ContentPresenter IsHitTestVisible="True" />
                                </Border>
                            </Border>
                            <ControlTemplate.Triggers>
    <!-- IsSelected does not appear to fire -->
                                <Trigger Property="IsSelected" Value="True" >
                                    <Setter TargetName="CarouselItemInnerBorder" Property="Background">
                                        <Setter.Value>
                                            <LinearGradientBrush EndPoint="108,472" StartPoint="108,23" MappingMode="Absolute">
                                                <GradientStop Color="#FF344B97" Offset="0"/>
                                                <GradientStop Color="#FF000000" Offset="1"/>
                                                <GradientStop Color="#FF233F7E" Offset="0.045"/>
                                                <GradientStop Color="#FF000000" Offset="0.0451"/>
                                            </LinearGradientBrush>
                                        </Setter.Value>
                                    </Setter>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </UserControl.Resources>
        <Grid>
            <telerik:RadCarousel x:Name="radCarousel" AutoGenerateDataPresenters="False" Loaded="radCarousel_Loaded" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden">
                <telerik:RadCarousel.ItemsPanel>               
                    <ItemsPanelTemplate>
                        <telerik:RadCarouselPanel x:Name="radCarouselPanel" IsScalingEnabled="True" IsOpacityEnabled="False" CanHorizontallyScroll="False" TopContainerChanged="RadCarouselPanel_TopContainerChanged" >                       
                        </telerik:RadCarouselPanel>
                    </ItemsPanelTemplate>
                </telerik:RadCarousel.ItemsPanel>
            </telerik:RadCarousel>
        </Grid>
    </UserControl>
  2. Vanya Pavlova
    Admin
    Vanya Pavlova avatar
    2019 posts

    Posted 20 Dec 2010 Link to this post

    Hi Phillip,

     
    I have prepared an example for you that contains a part of your code snippet. However I am not quite sure what happened behind the following RadCarouselPanel_TopContainerChanged event as well as the defined DataTemplate that uses CarouselScrollViewer and where it has been set.

    Feel free to modify the attached example and sent it back to me via support ticket if needed.

    Regards,
    Vanya Pavlova
    the Telerik team
    Browse the videos here>> to help you get started with RadControls for WPF
  3. UI for WPF is Visual Studio 2017 Ready
  4. Phillip
    Phillip avatar
    2 posts
    Member since:
    Jun 2008

    Posted 20 Jan 2011 Link to this post

    Thanks but that doesn't really help me with my problem. Do you have a sample of the carousel where each carousel item in the list has a sublist of items and both are keyboard navigable?
    The keyboard navigation is a particular problem for me with this control. It behaves the same whether Up / Left or Right / Down are pressed. I need the Up / Down to control the top list and Left / Right to move the sublist. Also, the keyboard navigation does not work until an item is clicked and keyboard navigation does not appear to update the selected item.

    I'd appreciate a quick response to help us continue our evaluation of the Telerik controls.

    EDIT: I've made a little progress but keyboard navigation is still messed up... I'm not sure if the RadCarousel will be suitable for this task as the navigation seems to be pretty poor. I've got the outer and inner carousels populating (except the inner carousel should be horizontal, not vertical) but navigating using the arrow keys yields strange results. I appreciate any help with this.

    MainWindow.xaml:

    <Window
        xmlns:sampleData="clr-namespace:Expression.Blend.SampleData.SampleDataSource"
        x:Class="WpfApplication24.MainWindow"
        x:Name="Window"
        Title="MainWindow"
        Width="640" Height="480">
    <Window.Resources>
            <Path
              x:Key="mainCarouselPath"
              Stretch="None"
              Opacity="1"
              Data="M0,0 C0,0 0,800 0,800"
              Stroke="#FFB4B4B4"
              StrokeThickness="4">
            </Path>
        </Window.Resources>
        <Grid x:Name="LayoutRoot" DataContext="{Binding Source={StaticResource SampleDataSource}}">
            <telerik:RadCarousel  x:Name="radCarousel" ItemsSource="{Binding Collection}" AutoGenerateDataPresenters="False"  HorizontalAlignment="Stretch" VerticalAlignment="Stretch" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden" SelectionChanged="radCarousel_SelectionChanged" Loaded="radCarousel_Loaded" PreviewMouseDown="Carousel_PreviewMouseDown" KeyUp="radCarousel_KeyUp">
                <telerik:RadCarousel.ItemTemplate>
                    <DataTemplate>
                        <telerik:RadCarousel x:Name="innerCarousel" AutoGenerateDataPresenters="False"  HorizontalAlignment="Stretch" VerticalAlignment="Stretch" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden" ItemsSource="{Binding Path=Children}" PreviewMouseDown="Carousel_PreviewMouseDown" KeyUp="radCarousel_KeyUp">
                            <telerik:RadCarousel.ItemsPanel>
                                <ItemsPanelTemplate>
                                    <telerik:RadCarouselPanel x:Name="radCarouselPanel" IsScalingEnabled="True" IsOpacityEnabled="False" CanHorizontallyScroll="True" CanVerticallyScroll="false" Path="{StaticResource mainCarouselPath}" >
                                    </telerik:RadCarouselPanel>
                                </ItemsPanelTemplate>
                            </telerik:RadCarousel.ItemsPanel>
                        </telerik:RadCarousel>
                    </DataTemplate>
                </telerik:RadCarousel.ItemTemplate>
                    <telerik:RadCarousel.ItemsPanel>              
                    <ItemsPanelTemplate>
                        <telerik:RadCarouselPanel x:Name="radCarouselPanel" IsScalingEnabled="True" IsOpacityEnabled="False" CanHorizontallyScroll="False" Path="{StaticResource mainCarouselPath}" >                                              
                        </telerik:RadCarouselPanel>
                    </ItemsPanelTemplate>               
                </telerik:RadCarousel.ItemsPanel>       
            </telerik:RadCarousel>
        </Grid>
    </Window>

    MainWindow.xaml.cs:
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Shapes;
    using Telerik.Windows.Controls;
     
    namespace WpfApplication24
    {
        /// <summary>
        /// Interaction logic for MainWindow.xaml
        /// </summary>
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                this.InitializeComponent();
                radCarousel.SelectedItem = radCarousel.Items[0];
                radCarousel.BringDataItemIntoView(radCarousel.Items[0]);
                // Insert code required on object creation below this point.
            }
     
            private void radCarousel_SelectionChanged(object sender, Telerik.Windows.Controls.SelectionChangeEventArgs e)
            {
                ((RadCarousel)sender).BringDataItemIntoView(((RadCarousel)sender).SelectedItem);
            }
     
            /*private void Window_KeyUp(object sender, KeyEventArgs e)
            {
                int offset = 0;
                RadCarousel carousel = null;
     
                if (e.Key == Key.Up)
                {
                    offset = -1;
                    carousel = radCarousel;
                    e.Handled = true;
                }
                else if (e.Key == Key.Down)
                {
                    offset = 1;
                    carousel = radCarousel;
                    e.Handled = true;
                }
                else if (e.Key == Key.Left || e.Key == Key.Right)
                {
                    if (e.Key == Key.Left)
                        offset = -1;
                    else if (e.Key == Key.Right)
                        offset = 1;
     
                    var panel = radCarousel.FindCarouselPanel();
                    var i = (panel.ItemContainerGenerator.GetItemContainerGeneratorForPanel(panel)
                            .ContainerFromItem(radCarousel.CurrentItem));
                    // Getting the ContentPresenter of myListBoxItem
                    if (i != null)
                    {
                        ContentPresenter myContentPresenter = FindVisualChild<ContentPresenter>(i);
     
                        // Finding textBlock from the DataTemplate that is set on that ContentPresenter
                        DataTemplate myDataTemplate = myContentPresenter.ContentTemplate;
                        //carousel = (RadCarousel)myDataTemplate.FindName("innerCarousel", myContentPresenter); // why is this null?                                               
                        var carouselList = myContentPresenter.ChildrenOfType<RadCarousel>();
                        if (carouselList.Count > 0)
                            carousel = carouselList[0];
                    }
                    e.Handled = true;
                }
                if (carousel != null)
                {
                    MoveCarousel(carousel, offset);
                    //radCarousel.FindCarouselPanel().MoveBy(offset);
                }
            }*/
     
     
            private void Carousel_PreviewMouseDown(object sender, MouseButtonEventArgs e)
            {
                CarouselScrollViewer scrollViewer = FindChild<CarouselScrollViewer>((RadCarousel)sender, null);
                scrollViewer.Focus();
            }
     
     
            public static T FindChild<T>(DependencyObject parent, string childName)
               where T : DependencyObject
            {
                // Confirm parent and childName are valid.
                if (parent == null) return null;
     
     
                T foundChild = null;
     
     
                int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
                for (int i = 0; i < childrenCount; i++)
                {
                    var child = VisualTreeHelper.GetChild(parent, i);
                    // If the child is not of the request child type child
                    T childType = child as T;
                    if (childType == null)
                    {
                        // recursively drill down the tree
                        foundChild = FindChild<T>(child, childName);
     
     
                        // If the child is found, break so we do not overwrite the found child.
                        if (foundChild != null) break;
                    }
                    else if (!string.IsNullOrEmpty(childName))
                    {
                        var frameworkElement = child as FrameworkElement;
                        // If the child's name is set for search
                        if (frameworkElement != null && frameworkElement.Name == childName)
                        {
                            // if the child's name is of the request name
                            foundChild = (T)child;
                            break;
                        }
                    }
                    else
                    {
                        // child element found.
                        foundChild = (T)child;
                        break;
                    }
                }
                return foundChild;
            }
     
     
            private childItem FindVisualChild<childItem>(DependencyObject obj) where childItem : DependencyObject
            {
                for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
                {
                    DependencyObject child = VisualTreeHelper.GetChild(obj, i);
                    if (child != null && child is childItem)
                        return (childItem)child;
                    else
                    {
                        childItem childOfChild = FindVisualChild<childItem>(child);
                        if (childOfChild != null)
                            return childOfChild;
                    }
                }
                return null;
            }
     
            private void MoveCarousel(RadCarousel carousel, int offset)
            {
                if (offset != 0)
                {
                    var items = carousel.Items;
                    for (int n = 0; n < items.Count; n++)
                    {
                        var item = items[n];
                        if (item == carousel.SelectedItem)
                        {
                            int index = n + offset;
                            if (index >= 0 && index < items.Count)
                            {
                                carousel.CurrentItem = items[index];
                                carousel.SelectedItem = items[index];
                                carousel.BringDataItemIntoView(items[index]);
                            }
                            break;
                        }
                    }
     
                }
            }
     
            private void radCarousel_Loaded(object sender, RoutedEventArgs e)
            {
                //var panel = this.radCarousel.FindCarouselPanel();
     
               // panel.IsScalingEnabled = false;
    //            panel.Path = (Path)this.Resources["mainCarouselPath"];       
            }
     
            private void radCarousel_KeyUp(object sender, KeyEventArgs e)
            {
                if (e.Key == Key.Up)
                {
                    //radCarousel.Focus();
                    CarouselScrollViewer scrollViewer = FindChild<CarouselScrollViewer>(radCarousel, null);
                    scrollViewer.Focus();
                    MoveCarousel(radCarousel, -1);
                    e.Handled = true;
                }
                else if (e.Key == Key.Right)
                {
                    //radCarousel.Focus();
                    CarouselScrollViewer scrollViewer = FindChild<CarouselScrollViewer>(radCarousel, null);
                    scrollViewer.Focus();
                    MoveCarousel(radCarousel, 1);
                    e.Handled = true;
                }
                else if (e.Key == Key.Left || e.Key == Key.Right)
                {
                    var panel = radCarousel.FindCarouselPanel();
                    var i = (panel.ItemContainerGenerator.GetItemContainerGeneratorForPanel(panel)
                            .ContainerFromItem(radCarousel.CurrentItem));
                    // Getting the ContentPresenter of myListBoxItem
                    RadCarousel innerCarousel = null;
                    if (i != null)
                    {
                        ContentPresenter myContentPresenter = FindVisualChild<ContentPresenter>(i);
     
                        // Finding textBlock from the DataTemplate that is set on that ContentPresenter
                        DataTemplate myDataTemplate = myContentPresenter.ContentTemplate;
                        //carousel = (RadCarousel)myDataTemplate.FindName("innerCarousel", myContentPresenter); // why is this null?                                               
                        var carouselList = myContentPresenter.ChildrenOfType<RadCarousel>();
                        if (carouselList.Count > 0)
                        {
                            innerCarousel = carouselList[0];
                            //innerCarousel.Focus();
                            CarouselScrollViewer scrollViewer = FindChild<CarouselScrollViewer>(innerCarousel, null);
                            scrollViewer.Focus();
                        }
                    }
                    if (innerCarousel != null)
                    {
                        if (e.Key == Key.Left)
                            MoveCarousel(innerCarousel, -1);
                        else if (e.Key == Key.Right)
                            MoveCarousel(innerCarousel, 1);
                        e.Handled = true;
                    }
                }
            }
        }
    }

    SampleData.xaml.cs - Item class
    public class Item : System.ComponentModel.INotifyPropertyChanged
    {
        public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
     
        public Item()
        {
            Children = new System.Collections.ObjectModel.ObservableCollection<String>();
            Children.Add(GetHashCode().ToString());
            Children.Add(GetHashCode().ToString());
            Children.Add(GetHashCode().ToString());
            Children.Add(GetHashCode().ToString());
            Children.Add(GetHashCode().ToString());
            Children.Add(GetHashCode().ToString());
        }
     
        protected virtual void OnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
            }
        }
     
        private string _Property1 = string.Empty;
     
        public string Property1
        {
            get
            {
                return this._Property1;
            }
     
            set
            {
                if (this._Property1 != value)
                {
                    this._Property1 = value;
                    this.OnPropertyChanged("Property1");
                }
            }
        }
     
        public System.Collections.ObjectModel.ObservableCollection<String> Children
        {
            get;
            private set;
        }
     
    }
  5. Milan
    Admin
    Milan avatar
    1989 posts

    Posted 27 Jan 2011 Link to this post

    Hello Phillip,

    RadCarousel contains a ScrollViewer control which will handle mouse and keyboard events. The logic that you are trying to implement is quite a special case and you will have to remove the ScrollViewer control to be able to achieve the desired result. 

    I have attached a sample project which demonstrates a sample implementation. 



    Regards,
    Milan
    the Telerik team
    Let us know about your Windows Phone 7 application built with RadControls and we will help you promote it. Learn more>>
Back to Top