Click here to Skip to main content
Click here to Skip to main content

Automatic Generation of Settings Page

, 6 Sep 2011
Rate this:
Please Sign up or sign in to vote.
Automatically generate a Windows Phone 7 settings page.

Introduction

Because most of our Windows Phone 7 applications require a configuration page to allow users to make any adjustments to the application itself and as this task is always a repetitive task that does not require any extra processing, I decided to create a simple application with a configuration page that is generated automatically, that may be helpful to us Windows Phone 7 developers.

Background

Since some time ago, in programming, it is a standard to save the settings of your application in XML format. I decided to use the XML format because it is very versatile and of course there are utilities that generate classes from an XML schema, so it is very easy to save or retrieve these settings using the serialization classes in .NET.

Code explanation

XML schema

The following image shows the XML schema that is used to generate our configuration. As shown, a configuration must have a name and data type, may also contain XAML code if you don't want to self-generate a control; or if the data type is defined as a string array, you must provide a list of string items.

Settings-schema.JPG

I've used JDeveloper to create this XML schema since I consider it as one of the best visual editors of XML schemas and also, because it is free. JDeveloper is a bit slow, so it is recommended to have a decent hardware with a good CPU, enough memory, and if you have a solid-state hard disk, much better.

The assignment of a data type to the configuration setting helps in the auto-generation of the configuration controls: if the String or Numeric data type is set, then a TextBox is generated; if it is a Boolean data type, it will generate a ToggleSwitch, and if it is a StringArray data type, it will generate a ListPicker control.

MVVM project

Our simple application consists of two pages: MainPage and SettingsPage, a data model that contains the XML schema, translation into code (XSD to class), and a sample configuration file (settings.xml). In turn, this application follows the convention of Model-View-View-Model (MVVM Light) by Laurent Bugnion.

Solution.JPG

The project also has a reference to Isolated Storage Explorer for WP7, that is because an application may require some tuning for the default configuration so that we can start with a pretty basic configuration and finalize with a configuration file (settings.xml tuned and tested, which in turn will become the default configuration file once the application gets deployed into marketplace).

Isolated-Storage-Explorer.JPG

In our application, we have used trivial and meaningless settings if you like, but it will serve well enough for demonstration purposes.

Let's now see the code in detail.

<settings xmlns="http://www.inputstudiowp7.com/schemas">
    <Setting Name="Use Location" Type="Boolean" Value="True"/>
    <Setting Name="Providers" Type="StringArray" Value="Item 2">
        <StringItem Value="Item 1"/>
        <StringItem Value="Item 2"/>
        <StringItem Value="Item 3"/>
    </Setting>
    <Setting Name="Nick Name" Type="String" Value="Undefined"/>
    <Setting Name="Age" Type="Integer" Value="18"/>
</settings>

The main page only has a few properties of our main Model-View and a hyperlink to the settings page. And the settings page is an empty Grid with self-generating controls once the page is loaded.

Main Page
Settings Page
MvvmSettings-Home.JPG MvvmSettings-SettingsPage.JPG

As for the self-generated controls in the settings page, when the loading of the page occurs, the code iterates through each of the settings and the input controls are generated according to its type, and a TextBlock is assigned as the label (Caption) and a numeric or text input scope if applicable. Once you leave the configuration page, the settings are saved.

public partial class SettingsPage : PhoneApplicationPage
{
    public MainViewModel model { get { return this.DataContext as MainViewModel; } }

    
    public SettingsPage()
    {
        InitializeComponent();
        this.Loaded += new System.Windows.RoutedEventHandler(Settings_Loaded);
    }

    void Settings_Loaded(object sender, System.Windows.RoutedEventArgs e)
    {
        Grid grid = this.FindName("LayoutRoot") as Grid;
        if (null != grid)
        {
            StackPanel spContent = new StackPanel();
            foreach (Setting setting in model.Settings.Setting)
            {
                TextBlock tbCaption = 
                  new TextBlock() { Text = string.Format("{0}", 
                  setting.Name.Trim()), Margin = new Thickness(12, 0, 0, 0) };
                switch (setting.Type)
                {
                    case eDataType.Boolean:
                        ToggleSwitch tsOption = new ToggleSwitch() 
                        { 
                            Name = string.Format("ts{0}", 
                              setting.Name.Replace(" ", string.Empty)), 
                              Header = setting.Name 
                        };
                        tsOption.SetBinding(ToggleSwitch.IsCheckedProperty, 
                          new Binding("Value") 
                          { Mode = BindingMode.TwoWay, Source = setting });
                        spContent.Children.Add(tsOption);
                        break;
                    case eDataType.String:
                    case eDataType.Integer:
                    case eDataType.Decimal:
                        TextBox txtValue = new TextBox()
                        {
                            Name = string.Format("txt{0}", 
                              setting.Name.Replace(" ", string.Empty)),
                            Height = 72,
                            MaxLength = 50,
                            TextWrapping = TextWrapping.NoWrap
                        };
                        txtValue.SetBinding(TextBox.TextProperty, 
                          new Binding("Value") { Mode = BindingMode.TwoWay, 
                          Source = setting });
                        txtValue.InputScope = new InputScope()
                        {
                            Names = { new InputScopeName() { 
                                NameValue = (setting.Type.Equals(eDataType.String) 
                                ? InputScopeNameValue.Text
                                : InputScopeNameValue.Number) } }
                        };

                        spContent.Children.Add(tbCaption);
                        spContent.Children.Add(txtValue);
                        break;
                    case eDataType.StringArray:
                        ListPicker lpValue = new ListPicker()
                        {
                            Header = string.Format("{0}", setting.Name.Trim())
                        };

                        List<string> items = new List<string>();
                        foreach (StringItem item in setting.StringItem)
                            items.Add(item.Value);

                            lpValue.ItemsSource = items;
                            lpValue.SetBinding(ListPicker.SelectedItemProperty, 
                              new Binding("Value") 
                              { Mode = BindingMode.TwoWay, Source = setting });
                            spContent.Children.Add(lpValue);
                        break;
                }
            } 
            grid.Children.Add(spContent);
        }
    }

    protected override void OnNavigatedFrom(
              System.Windows.Navigation.NavigationEventArgs e)
    {
        model.saveSettings();

        base.OnNavigatedFrom(e);
    }
}

As an extra, the application sends an email when a catastrophic failure occurs.

Points of interest

If you find this auto-generated settings page useful, the Visual Studio templates may be modified to include this page and setting the configuration items.

This is just a starting point for building a fully configurable settings page.

History

First version of this post. Here is my second post in CodeProject.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

EmitsorGrp
Software Developer (Senior) Emitsor Group
Mexico Mexico
Focused on creating MS Windows 8, Silverlight, Windows Phone 7 & 8 and the Web applications.
 
More than 20 years of experience creating software solutions.
Follow on   Twitter

Comments and Discussions

 
GeneralFantastic! Pinpremium_ Kunal Chowdhury _21-Jul-14 0:20 
GeneralMy vote of 5 PinmvpKanasz Robert21-Sep-12 1:39 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140721.1 | Last Updated 6 Sep 2011
Article Copyright 2011 by EmitsorGrp
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid