Designing an app with dynamic tabs

15 posts, 2 answers
  1. Jack Helm
    Jack Helm avatar
    18 posts
    Member since:
    Jan 2010

    Posted 23 Apr 2010 Link to this post

    I am reletivly new to the silverlight world and have a design question to see if what I am looking to do is possible and if anyone can point me in the correct way to do it. My problem is that I may not know the correct terminology to ask the right questions.

    What I am trying to build is an app that has a drop down box and a Tab Control. When a selection is made in the drop down, I will go to the database and gather all the information I need to populate a collection of complex objects in client side code. Once I have these, for each complex objects called agents, I need to create a tab and name them (Agent X, Agent Y, Agent Z) and populate the 20 or so controls on each tab with the data from the agent object represented on the tab.

    However I never know how many tabs that may involve. So rather than create a whole new group of controls on each tab, what I would like to do is have one set of controls and rebind the controls to a different Agent object in my collection according to the tab selected.

    So I guess my first question is can I have a common set of controls that each tab will access? Or do i need to build a different set of controls for each tab?
  2. Kiril Stanoev
    Admin
    Kiril Stanoev avatar
    1511 posts

    Posted 28 Apr 2010 Link to this post

    Hi Jack,

    If I've understood you correctly, I'd suggest you use ItemTemplate and ContentTemplate of RadTabControl. I've prepared a sample project that shows how to use these templates and bind the data coming from the database. The project has no database connection, that is why the data source for the TabControl is created in the code-behind, but the approach is the same. Get familiar with the project and let me know how it works for you. If you have further questions or comments, I'd be glad to further assist you.

    Kind regards,
    Kiril Stanoev
    the Telerik team

    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
  3. DevCraft banner
  4. Jack Helm
    Jack Helm avatar
    18 posts
    Member since:
    Jan 2010

    Posted 28 Apr 2010 Link to this post

    Kiril,
    That would be great help. I very much appreciate it. One question whose answer is apparently aluding me is how do I download your example? I do not see any link for downloading.

    Again, many MANY thanks.

    Jack
  5. Kiril Stanoev
    Admin
    Kiril Stanoev avatar
    1511 posts

    Posted 28 Apr 2010 Link to this post

    Hello Jack Helm,

    Sorry about that. Something must have gotten wrong with the support system. The project will be attached to this message.

    Greetings,
    Kiril Stanoev
    the Telerik team

    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
  6. Jack Helm
    Jack Helm avatar
    18 posts
    Member since:
    Jan 2010

    Posted 28 Apr 2010 Link to this post

    Kiril,

    when I try to open the sln file I get an error saying it was created by a newer version of this application and cannot be opened. I am using Visual Studio 2008. What did you create this demo in?
  7. Kiril Stanoev
    Admin
    Kiril Stanoev avatar
    1511 posts

    Posted 28 Apr 2010 Link to this post

    Hello Jack,

    I used Visual Studio 2010 for the demo project. I've converted it to Visual Studio 2008. Let me know if you experience any additional problems.

    Sincerely yours,
    Kiril Stanoev
    the Telerik team

    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
  8. Jack Helm
    Jack Helm avatar
    18 posts
    Member since:
    Jan 2010

    Posted 28 Apr 2010 Link to this post

    Kiril,

    I have looked over the code and indeed I think this will do exactly what I was hoping for. I have a few questions for you on it though.

    1. I assume that the binding does allow for two way binding so that I can use the text boxes to alter the data/properties of the object bound to it?

    2. I am looking in the MainPage.Xaml and I see where you call the static resource from the UserControl.Resources section. And I see the templates setup in the resources section. But I thought in order to setup a local resource you had to create a namespace for it and I do not see any namespace pointing to the class declaration. is this not required in this situation (Obviously not, since it works but why?)

    I am sure I will have plenty more as I try to implement my code for this. Thanks for your help. It is a great relief to finally not be hammering this out alone with nobody to ask questions of.

    Jack
  9. Jack Helm
    Jack Helm avatar
    18 posts
    Member since:
    Jan 2010

    Posted 03 May 2010 Link to this post

    Kiril,

    I have been progressing well using your example as a jumping off point. But I have run into a little glitch. I need to put a RadGridView on the tabs and bind it to a list of objects that are part of the object that the tab is bound to. Would this also be done with a Datatemplate in the UserControl:Resources section as a DataTemplate?
  10. Answer
    Ivan
    Admin
    Ivan avatar
    519 posts

    Posted 04 May 2010 Link to this post

    Hi Jack Helm,

    Please preview the attached here example and let us know if you need further explanation.

    Regards,
    Ivan
    the Telerik team

    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
  11. Jack Helm
    Jack Helm avatar
    18 posts
    Member since:
    Jan 2010

    Posted 06 May 2010 Link to this post

    Tha tis outstanding. I finally am beginning to understand how this works. One new question that has come up, I have played around with it but have not figured out yet how it is going to work in this scenerio. I am using a scenerio similar to the one in your example. but I need to add vertical scroll bars to the tab item so that when the body of the tab item grows beyond the height of the window, I can scroll. Currently my content is just beyond the reach unless I can widen the Explorer window. Using your example, how would you add the scrollbars (or scrollviewer? Not sure the differences there) to it?
  12. Answer
    Ivan
    Admin
    Ivan avatar
    519 posts

    Posted 07 May 2010 Link to this post

    Hello Jack Helm,

    You can achieve it very easy. Just Use the ScrollViewer as container of your content. Something like:
     
    <DataTemplate x:Key="TabContentTemplate">
        <ScrollViewer
             HorizontalScrollBarVisibility="Auto"
            VerticalScrollBarVisibility="Auto"
            >
            <Your Content Here . . .
     
    Please preview the attached example and let us know how it fits your requirements.


    Kind regards,
    Ivan
    the Telerik team

    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
  13. Jack Helm
    Jack Helm avatar
    18 posts
    Member since:
    Jan 2010

    Posted 07 May 2010 Link to this post

    I tried to put the scrollviewer inside the tabcontrol and the scroll bar showed up but when I tested it by enlarging the size of the items inside the tab control beyond the height I had given it, they never activated or got bars in them to allow me to scroll. I was, however able to put them on the overall page and that will allow me to scroll, oif not how I was hoping, certainly adequate for this project. Thanks.
  14. Tina Stancheva
    Admin
    Tina Stancheva avatar
    3298 posts

    Posted 12 May 2010 Link to this post

    Hi Jack Helm,

    We are glad that you managed to find a solution for the problem.

    Let us know if you need more info.

    Regards,
    Tina Stancheva
    the Telerik team

    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
  15. Angie
    Angie avatar
    33 posts
    Member since:
    Jul 2010

    Posted 06 Dec 2011 Link to this post

    When i tried MVVM Bindings i get problem when changing selectedIndex. I could send a project solution (i tried attaching but didn't allow me to). Let me know. When you click Next Agent button i don't see anytabs getting selected

    ViewModel

    using System;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Ink;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;
     
    namespace SilverlightApplication1.ViewModel
    {
        public class AgentsVMINotifyPropertyChanged 
        {
            private int index;
            public int SelectedIndex
            {
                get
                {
                    return index;
                }
                set { 
                    index = value;
                    RaisePropertyChanged("SelectedIndex");
                }
            }
     
            public void IncreaseTab()
            {
                index++;
                _agents = null;
                RaisePropertyChanged("Agents");
                RaisePropertyChanged("SelectedIndex");
            }
            private ObservableCollection<Agent> _agents;
            public ObservableCollection<Agent> Agents
            {
                get
                {
                    if (_agents == null)
                    {
                        _agents = new ObservableCollection<Agent>();
                        Agent agent1 = new Agent();
                        agent1.Title = "Agent #1";
                        agent1.AgentInformation.BirthDate = new DateTime(1975, 01, 20);
                        agent1.AgentInformation.FirstName = "Mike";
                        agent1.AgentInformation.LastName = "Henderson";
                        _agents.Add(agent1);
     
                        Agent agent2 = new Agent();
                        agent2.Title = "Agent #2";
                        agent2.AgentInformation.BirthDate = new DateTime(1986, 05, 01);
                        agent2.AgentInformation.FirstName = "John";
                        agent2.AgentInformation.LastName = "Madox";
                        _agents.Add(agent2);
     
                        Agent agent3 = new Agent();
                        agent3.Title = "Agent #3";
                        agent3.AgentInformation.BirthDate = new DateTime(1950, 12, 15);
                        agent3.AgentInformation.FirstName = "Steve";
                        agent3.AgentInformation.LastName = "Livingston";
                        _agents.Add(agent3);
                    }
                    return _agents;
                }
            }
     
            public RelayCommand CmdNextAgent
            {
                get
                {
                    return new RelayCommand(
                        () => this.IncreaseTab()
                        );
                }
            }
            #region INotifyPropertyChanged Members
     
            public event PropertyChangedEventHandler PropertyChanged;
     
            public void RaisePropertyChanged(string propertyName)
            {
               
                    if (PropertyChanged != null)
                        PropertyChanged(thisnew PropertyChangedEventArgs(propertyName));
            }
     
            #endregion
        }
     
        public class RelayCommandICommand
        {
            private Action _action;
     
            public RelayCommand(Action action)
            {
                _action = action;
            }
     
            #region ICommand Members
     
            public bool CanExecute(object parameter)
            {
                return true;
            }
     
            public event EventHandler CanExecuteChanged;
     
            public void Execute(object parameter)
            {
                _action();
            }
     
            #endregion
        }
    }
    
    using System;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Ink;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;
     
    namespace SilverlightApplication1.ViewModel
    {
        public class AgentsVMINotifyPropertyChanged 
        {
            private int index;
            public int SelectedIndex
            {
                get
                {
                    return index;
                }
                set { 
                    index = value;
                    RaisePropertyChanged("SelectedIndex");
                }
            }
     
            public void IncreaseTab()
            {
                index++;
                _agents = null;
                RaisePropertyChanged("Agents");
                RaisePropertyChanged("SelectedIndex");
            }
            private ObservableCollection<Agent> _agents;
            public ObservableCollection<Agent> Agents
            {
                get
                {
                    if (_agents == null)
                    {
                        _agents = new ObservableCollection<Agent>();
                        Agent agent1 = new Agent();
                        agent1.Title = "Agent #1";
                        agent1.AgentInformation.BirthDate = new DateTime(1975, 01, 20);
                        agent1.AgentInformation.FirstName = "Mike";
                        agent1.AgentInformation.LastName = "Henderson";
                        _agents.Add(agent1);
     
                        Agent agent2 = new Agent();
                        agent2.Title = "Agent #2";
                        agent2.AgentInformation.BirthDate = new DateTime(1986, 05, 01);
                        agent2.AgentInformation.FirstName = "John";
                        agent2.AgentInformation.LastName = "Madox";
                        _agents.Add(agent2);
     
                        Agent agent3 = new Agent();
                        agent3.Title = "Agent #3";
                        agent3.AgentInformation.BirthDate = new DateTime(1950, 12, 15);
                        agent3.AgentInformation.FirstName = "Steve";
                        agent3.AgentInformation.LastName = "Livingston";
                        _agents.Add(agent3);
                    }
                    return _agents;
                }
            }
     
            public RelayCommand CmdNextAgent
            {
                get
                {
                    return new RelayCommand(
                        () => this.IncreaseTab()
                        );
                }
            }
            #region INotifyPropertyChanged Members
     
            public event PropertyChangedEventHandler PropertyChanged;
     
            public void RaisePropertyChanged(string propertyName)
            {
               
                    if (PropertyChanged != null)
                        PropertyChanged(thisnew PropertyChangedEventArgs(propertyName));
            }
     
            #endregion
        }
     
        public class RelayCommandICommand
        {
            private Action _action;
     
            public RelayCommand(Action action)
            {
                _action = action;
            }
     
            #region ICommand Members
     
            public bool CanExecute(object parameter)
            {
                return true;
            }
     
            public event EventHandler CanExecuteChanged;
     
            public void Execute(object parameter)
            {
                _action();
            }
     
            #endregion
        }
    }
    

    <UserControl x:Class="SilverlightApplication1.MainPage"
    		xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    		xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    		xmlns:telerik="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls"
    		xmlns:telerikInput="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.Input"
    		xmlns:telerikNavigation="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.Navigation">
    	<UserControl.Resources>
    		<DataTemplate x:Key="AgentHeaderTemplate">
    			<Grid>
    				<TextBlock Text="{Binding Path=Title}" />
    			</Grid>
    		</DataTemplate>
    		<DataTemplate x:Key="AgentContentTemplate">
    			<Grid>
    				<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
    					<TextBlock Text="First Name:" Margin="0 10 0 0" />
    					<TextBox Text="{Binding Path=AgentInformation.FirstName}" IsReadOnly="True" />
    					<TextBlock Text="Last Name:" Margin="0 10 0 0" />
    					<TextBox Text="{Binding Path=AgentInformation.LastName}" IsReadOnly="True" />
    					<TextBlock Text="Birth Date:" Margin="0 10 0 0" />
    					<telerikInput:RadCalendar DisplayMode="MonthView"
    							DisplayDate="{Binding Path=AgentInformation.BirthDate}"
    							SelectedDate="{Binding Path=AgentInformation.BirthDate}" />
    				</StackPanel>
    			</Grid>
    		</DataTemplate>
    	</UserControl.Resources>
    	<Grid x:Name="LayoutRoot" Background="White">
    		<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
    			<telerikNavigation:RadTabControl x:Name="tabControl1" Width="500" Height="500"
                                                 SelectedIndex="{Binding SelectedIndex}"
                        ItemsSource="{Binding Agents}"
    					ItemTemplate="{StaticResource AgentHeaderTemplate}"
    					ContentTemplate="{StaticResource AgentContentTemplate}" />
    			<Button Content="Load Data" Click="LoadDataButton_Click" />
     
                <Button Command="{Binding CmdNextAgent}" Content="Next Agent"/>
            </StackPanel>
    	</Grid>
    </UserControl>

    ----------------------------
    App.xaml.cs


    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;
    using SilverlightApplication1.ViewModel;
     
    namespace SilverlightApplication1
    {
    	public partial class App : Application
    	{
     
    		public App()
    		{
    			this.Startup += this.Application_Startup;
    			this.Exit += this.Application_Exit;
    			this.UnhandledException += this.Application_UnhandledException;
     
    			InitializeComponent();
    		}
     
    		private void Application_Startup(object sender, StartupEventArgs e)
    		{
    		    var AgentsVM = new AgentsVM();
    		    var mainPage = new MainPage(){DataContext=AgentsVM};
     
                this.RootVisual = mainPage;
    		}
     
    		private void Application_Exit(object sender, EventArgs e)
    		{
     
    		}
     
    		private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
    		{
    			// If the app is running outside of the debugger then report the exception using
    			// the browser's exception mechanism. On IE this will display it a yellow alert 
    			// icon in the status bar and Firefox will display a script error.
    			if (!System.Diagnostics.Debugger.IsAttached)
    			{
     
    				// NOTE: This will allow the application to continue running after an exception has been thrown
    				// but not handled. 
    				// For production applications this error handling should be replaced with something that will 
    				// report the error to the website and stop the application.
    				e.Handled = true;
    				Deployment.Current.Dispatcher.BeginInvoke(delegate { ReportErrorToDOM(e); });
    			}
    		}
     
    		private void ReportErrorToDOM(ApplicationUnhandledExceptionEventArgs e)
    		{
    			try
    			{
    				string errorMsg = e.ExceptionObject.Message + e.ExceptionObject.StackTrace;
    				errorMsg = errorMsg.Replace('"''\'').Replace("\r\n"@"\n");
     
    				System.Windows.Browser.HtmlPage.Window.Eval("throw new Error(\"Unhandled Error in Silverlight Application " + errorMsg + "\");");
    			}
    			catch (Exception)
    			{
    			}
    		}
    	}
    }
    
  16. Kiril Stanoev
    Admin
    Kiril Stanoev avatar
    1511 posts

    Posted 08 Dec 2011 Link to this post

    Hello Ravindranath,

     I made couple of modifications to your project.

    public void IncreaseTab()
    {
        this.SelectedIndex += 1;
        //_agents = null;
        //RaisePropertyChanged("Agents");
        //RaisePropertyChanged("SelectedIndex");
    }

    *** I am not sure whether you have to null the agents.

    <telerikNavigation:RadTabControl x:Name="tabControl1" Width="500" Height="500"
                        SelectedIndex="{Binding SelectedIndex, Mode=TwoWay}"

    Binding should be two-way.

    Greetings,
    Kiril Stanoev
    the Telerik team

    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

Back to Top
DevCraft banner