Telerik blogs

imageConference Buddy is a real-world Line of Business application that we are building and documenting as we build. You can learn more about it here. You can find a list of related blog posts here

We need to capture, preserve and use the following information for Conference Buddy

  • User Name
  • User Password
  • URL of the back-end data service

The preferred way to obtain this information is through the Settings Charm in windows 8, as shown in the cropped illustration.

The user slides the Charms into view (or presses Windows-C) and chooses Settings. The user then taps on Authentication and our custom authentication window opens with prompts and TextBoxes to fill in the data we need.

We will preserve the user name and url in local settings and the password in the Credential Locker. We will then use them when needed to contact the back end database that stores and manages all the data collected in the application.

 

Getting Started Creating the Settings Page

The Settings page will be displayed on request of the user, and the settings themselves will be preserved when the page is dismissed. There is no explicit save button.

Special thanks to Pete Brown and his book Windows Store App Development (Manning, 2013), Carey Payette and to the folks on Stack Overflow for helping me understand how to put all this together.

We begin by creating a class which will manage the saving and loading of the settings. We’ll call this SettingsService.cs. This class has three static properties,

public static string UserName { get; set; }
public static string UserPW { get; set; }
public static string ServerURL { get; set; }

 

The constructor registers for the ApplicationData.Current.DataChanged event, the handler looks like this:

private static void OnDataChanged( ApplicationData sender, object args )
{
Load();
}

The Load event obtains the UserName and ServerURL from LocalSettings (we’ll see how they are stored in just a moment), using the following constants,

private const string UserNameKey = "User Name";
private const string ServerURLKey = "Connection URL";
private const string ResourceKey = "login";

 

The retrieval is accomplished by indexing into the LocalSettings collection,

UserName = ApplicationData.Current.
LocalSettings.Values[UserNameKey].ToString();
ServerURL = ApplicationData.Current.
LocalSettings.Values[ServerURLKey].ToString();

 

The password is retrieved from the PasswordVault using the Credential Locker,

var vault = new PasswordVault();
var retrievedCredential = vault.Retrieve(
ResourceKey, UserName );
UserPW = retrievedCredential.Password;

 

Saving is just the inverse of Loading,

public static void Save() 
{
var current = ApplicationData.Current;
current.LocalSettings.Values[ServerURLKey] = ServerURL;
current.LocalSettings.Values[UserNameKey] = UserName;
var credential = new PasswordCredential(
ResourceKey, UserName, UserPW );
var vault = new PasswordVault();
vault.Add( credential );

}

Notice that both Load and Save are public and static. We’ll see why in just a moment.

Creating SettingsAuthenticationViewModel

Before we create the SettingsAuthenticationPage itself, let’s begin by creating its associated ViewModel. This VM has three public properties (UserName, UserPW and ServerURL) as well as two methods, Save and Load. The methods delegate their work to the static methods we just created in SettingsService.

 

<Grid Grid.Row="1"
Margin="30"
Name="FlyoutPanel">
<StackPanel>
<StackPanel Margin="0,0,0,10"
Width="350"
HorizontalAlignment="Left">
<TextBlock Text="User name"
Style="{StaticResource CaptionTextStyle}"
Foreground="Black" />
<TextBox Text="{Binding UserName, Mode=TwoWay}"
Margin="0,5,0,0"
BorderBrush="Black" />
</StackPanel>

<StackPanel Margin="0,0,0,10"
Width="350"
HorizontalAlignment="Left">
<TextBlock Text="User password"
Style="{StaticResource CaptionTextStyle}"
Foreground="Black" />
<PasswordBox Password=
"{Binding UserPW, Mode=TwoWay}"
Margin="0,5,0,0"
BorderBrush=" Black" />

</StackPanel>

<StackPanel Margin="0,0,0,10"
Width="350"
HorizontalAlignment="Left">
<TextBlock Text="Server URL"
Style="{StaticResource CaptionTextStyle}"
Foreground="Black" />
<TextBox Text="{Binding ServerURL, Mode=TwoWay}"
Margin="0,5,0,0"
BorderBrush=" Black" />
</StackPanel>
</StackPanel>
</Grid>

The Code Behind

The Code-behind page for the SettingsAuthenticationPage sets up the View Model,

private SettingsAuthenticationViewModel _vm;
public SettingsOptionsPage()
{
this.InitializeComponent();

_vm = new SettingsAuthenticationViewModel();
DataContext = _vm;

this.Unloaded += SettingsOptionsPage_Unloaded;
}

Notice that we’ve added an event handler for when the page is unloaded. This is when we’ll persist the data we’ve collected,

void SettingsOptionsPage_Unloaded( 
object sender, RoutedEventArgs e )
{
if (_vm != null)
_vm.Save();
}

Our final task is to handle the BackButton click event. In this case we want to close the popup but open the settings pane. You can open the settings pane from anywhere by calling SettingsPane.Show

private void OnSettingsBackButtonClick( 
object sender, RoutedEventArgs e )
{
var parent = this.Parent as Popup;
parent.IsOpen = false;

SettingsPane.Show();
}

 

The work of actually displaying the SettingsPane is delegated to a new class that we’ll create in the Services folder, SettingsPageService.

public class SettingsPaneService : IDisposable
{
private Popup _settingsPopup;

 

In the constructor we add a handler for the CommandsRequested event of the SettingsPage,

public SettingsPaneService()

{

SettingsPane.GetForCurrentView().CommandsRequested +=

OnSettingsPaneCommandsRequested;

}

 

Note that you must have only a single listener on the CommandsRequested event so you want to be sure to remove the handler when the class is destroyed.

The bulk of the work is done in the event handler for the CommandsRequested event,

private const int SettingsPageID = 1001;
private void OnSettingsPaneCommandsRequested(
SettingsPane sender,
SettingsPaneCommandsRequestedEventArgs args )
{
var Authentications = new SettingsCommand(
SettingsPageID, "Authentication",
( x ) =>
{
var fullWidth =
Window.Current.CoreWindow.Bounds.Width;
var fullHeight =
Window.Current.CoreWindow.Bounds.Height;

const int PaneWidth = 635;

_settingsPopup = new Popup();

_settingsPopup.Closed += OnPopupClosed;
Window.Current.Activated += OnWindowActivated;

_settingsPopup.IsLightDismissEnabled = true;
_settingsPopup.Width = PaneWidth;
_settingsPopup.Height = fullHeight;

SettingsOptionsPage mypane = new SettingsOptionsPage();

mypane.Width = PaneWidth;
mypane.Height = fullHeight;

_settingsPopup.Child = mypane;
_settingsPopup.SetValue(
Canvas.LeftProperty, fullWidth - PaneWidth );
_settingsPopup.SetValue( Canvas.TopProperty, 0 );
_settingsPopup.IsOpen = true;


} );

args.Request.ApplicationCommands.Add( Authentications );
}

The width of the settings pane is under your control. Here we’ve made it a bit wider than absolutely necessary so that the controls have a little “breathing room”.

Making It All Work

Of course, none of this will actually do anything until we wire it up in one or more pages. We’ll start in the EventList page’s OnNavigation. At the bottom of that method, we add these two lines of code:

if (_settingsPaneService == null)
_settingsPaneService = new SettingsPaneService();

That’s all it takes to activate our settings from that page.

App.Xaml

It is most convenient to have the settings loaded when the application begins. To accomplish that we’ll open App.xaml.cs and find the OnLaunched event handler, where we’ll add this one line of code,

SettingsService.Load();

Note that I’ve put in virtually no error handling, and the code shown is stripped down to its essentials

 

That’s all it takes to add settings to your program, and in this case, to gather the information necessary to create a connection to the server. The code that actually uses these settings looks like this:

private Proxy GetProxy()
{
string url = SettingsService.ServerURL;
string user = SettingsService.UserName;
string pw = SettingsService.UserPW;

var cbProxy = new ConferenceBuddy.PortableClient.Proxy(
new Uri(url), user, pw);
return cbProxy;
}

 

We can then call GetProxy to get a proxy connection and use that to retrieve events, contacts, etc.

 

NOTICE: This process will change in Windows 8.1 where there is more support for the settings tab out of the box.  More on this in coming weeks.

Win8_Download (2)

Download RadControls for WPF Download RadControls for Silverlight

About the author

Jesse Liberty

Jesse Liberty

Jesse Liberty is a Technical Evangelist for Telerik and has three decades of experience writing and delivering software projects. He is the author of 2 dozen books as well as courses on Pluralsight on Windows 8 and WPF. Jesse has been a Distinguished Software Engineer for AT&T and a VP for Information Services for Citibank and a Software Architect for PBS. You can read more on his personal blog and his Telerik blog or follow him on twitter


jesseLiberty
About the Author

Jesse Liberty

 has three decades of experience writing and delivering software projects. He is the author of 2 dozen books and has been a Distinguished Software Engineer for AT&T and a VP for Information Services for Citibank and a Software Architect for PBS. You can read more on his personal blog or follow him on twitter

Comments

Comments are disabled in preview mode.