Archive

Archive for the ‘Metro’ Category

Windows 8 New UI Apps FilePicker

September 9, 2012 Leave a comment

Every Win 8 app does live in its own sandbox. Communication between apps is very limited.

The following picture does show the possible interaction ways:

image

In theory, any developer can require access to the users filesystem places by checking the matching capabilities in the app manifest.

But this will ask the user on the first start, whether he want to allow access the app to this specific places.

And: Some of the capabilities can only be requested by developers, who have registered a company account!

The reasons, that this is in almost all the cases not a very good idea, is data privacy. If a user allows access to his data folders, then the app could transfer all data to any place in the internet.

==> Capabilities for allowing access to the users data locations should be used very seldom due to potential data privacy issues!

image

But even in the scenario, that the user will allow access to this places:

The app will never be able to transfer data to or from the users desktop or any other filesystem location, because the access is limited to the e.g. Documents libarary.

 

If your app needs to transfer data to any location on the users filesystem, then the concept of FilePicker will be very helpful.

FileOpenPicker and FileSavePicker are a way to ask the user to provide a file. The user can then navigate to any place on the local filesystem or even on any connected network filesystem and select a file.

Using FileOPenPicker the user will see this and can switch between all this places:

image                                                           image

The big difference then is, that the user is in charge and can decide whether he really wants to allow the app to access this file.

The app can never access this file without the users explicit action.

There is even another big advantage using the FilePicker interface:

It’s not only limited to the local and network filesystem, but can access a lot of other places, like Skydrive and other third party apps. You can even provide a FilePicker interface in your app, which then acts as source for data read/write operations to other apps.

Another very nice feature of this interface is, that reading and writing to any source/destination which the user has selected, is as easy as reading from a local file. There is no difference and the app code must not handle any special cases. It is just reading or writing through the FileOpen- or FileSavePicker interface.

Using the FileOpenPicker from code requires only a few lines of code:

private async void LoadFileUsingFilePicker()
{
    FileOpenPicker fop = new FileOpenPicker();
    fop.SuggestedStartLocation = PickerLocationId.ComputerFolder;
    fop.ViewMode = PickerViewMode.List;
    fop.FileTypeFilter.Add(".txt");
    fop.FileTypeFilter.Add(".cs");
    var storageFile = await fop.PickSingleFileAsync();
    if (storageFile != null)
    {
        var lines = await FileIO.ReadLinesAsync(storageFile);
        if (lines != null)
        {
            for (int i = 0; i < lines.Count; i++)
            {
                txtData.Text += lines[i];
            }
        }

    }
}


The same applies for saving a file to any location on the users filesystem

(but on behalf of the user):

private async void SaveFileUsingFilePicker()
{
    FileSavePicker fsp = new FileSavePicker();
    fsp.SuggestedStartLocation = PickerLocationId.Desktop;
    fsp.FileTypeChoices.Add("Text file", new string[] { ".txt" });
    fsp.SuggestedFileName = "NewFile.txt";
    fsp.DefaultFileExtension = ".txt";
    StorageFile storageFile = await fsp.PickSaveFileAsync();
    if (storageFile != null)
    {
        await FileIO.WriteTextAsync(storageFile, txtData.Text);
    }
}
Categories: Metro, Windows 8

Windows 8 AppBar

September 8, 2012 2 comments

New UI Style apps are always fullscreen and do not display any chrome like borders or frames. Functionality should be placed on data items instead. But in some cases additional functionality is needed. One of the possible solutions for this, is to use the AppBar concept.

Windows 8 apps can provide AppBar on the top or on the bottom of the app itslef.

Some examples:
Internet Explorer is using the top AppBar for switching / adding tabs and the bottom bar for display of the Url input field and the users favorites.

The following picture shows both AppBars, which is in reality not possible. You can either display the top or the bottom AppBar, but not both at the same time. (Other apps will show both at the same time)

Invoking the AppBar can be done by swiping from the top border or from the bottom border on a touch device. Right click with the mouse or WinKey + Z will have the same effect.

 

image

 

Adding a AppBar to the bottom of a page

To add a AppBar at the bottom of your own program, the following definition must be added to the XAML-page:

<Page.BottomAppBar>
    <AppBar Name="PageAppBar" IsOpen="True" IsSticky="True">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="*" />
            </Grid.ColumnDefinitions>

            <StackPanel Orientation="Horizontal" 
                        Grid.Column="0" HorizontalAlignment="Left">
                <Button x:Name="btnFilePicker" 
                        Style="{StaticResource OpenFileAppBarButtonStyle}" 
                        Click="btnFilePicker_Click_1" />
            </StackPanel>
            <StackPanel Orientation="Horizontal" 
                        Grid.Column="1" HorizontalAlignment="Right">
                <Button x:Name="btnAdd" 
                        Style="{StaticResource AddAppBarButtonStyle}" 
                        Click="btnAdd_Click_1" />
            </StackPanel>
        </Grid>

    </AppBar>
</Page.BottomAppBar>

The bottom AppBar in this example is split into a left and right part. UI Style guide recommends, that the commands on the right side should be selection specific, while the commands on the left side should be global and not specific to any selection.

In this case the button on the bottom left will open the FileOpenPicker and the button on the bottom right will create a new item.

The symbols in this buttons are automatically added by using predefined styles.

Look into Common/StandardStyles.xaml and you will find a lot of predefined styles.

BUT: Most of them are commented out and you need to uncomment the one, you want to use

After adding the XAML above to a blank page you will get the following UI:

image

The attributes IsOpen="True" will display the AppBar all the time. Without the attribut, the user must first invoke the AppBar, either with a swipe from the bottom or WinKey + Z.

The default and recommended behavior is, that AppBar is NOT visible all the time.

The attribute IsSticky="True" will leave the AppBar open, even after a button was clicked on the AppBar. This is again not the default behavior. The recommended default behavior is, that the AppBar must be manually invoked and then will be hidden after using it.

 

Adding a AppBar to the top of a page

To add a AppBar at the top, the following XAML must be added to the page:

<Page.TopAppBar>
    <AppBar Name="PageTopAppBar" IsOpen="False" IsSticky="False">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="*" />
            </Grid.ColumnDefinitions>
                
            <StackPanel Grid.Column="0" 
                        Orientation="Horizontal" HorizontalAlignment="Left">
                <Button Name="btnTopLeft" 
                        Style="{StaticResource StreetAppBarButtonStyle}" />
            </StackPanel>

            <StackPanel Grid.Column="1" 
                        Orientation="Horizontal" HorizontalAlignment="Right">
                <Button Name="btnTopRight" 
                        Style="{StaticResource MapAppBarButtonStyle}" />
            </StackPanel>            
        </Grid>
    </AppBar>
</Page.TopAppBar>

Again, the highlighted style definitions must be uncommented from StandardStyles.xaml.

The app will then look like this:

image

 

[EDIT]

I’ve added the sample project as attachement here: BottomAppBarSample.zip

 .

Categories: Metro, Windows 8

Windows 8 Apps: Page navigation with XAML

September 8, 2012 Leave a comment

Windows 8 Apps are always fullscreen. The concept of overlapping windows like in Desktop applications is not existing. Only popup style dialogs are ok to use. In most scenarios it will be necessary to have different windows for displaying different data. Only one window is vivible at any time. All previous windows are hidden.

But Windows can track the list of previously displayed windows inside a single application.

Every page, except for the main page will show a back button at the top left corner. This concept is known from Windows Phone and makes it easy for users to navigate inside the app.

It is recommended to use the template "Basic Page" for all pages, which is inheriting a lot of functionality from inside the LayoutAwarePage class.

The Navigation functionality is placed inside the Frame class.

rootFrame.Navigate(typeOf(DestinationPage), objParam) allows to change to the given page by just using its typename.

There are is also GoBack and GoForward() functions, which act on the current stack.

The properties CanGoBack and CanGoForward can be used as an indicator, whether it’s useful to display the BackButton or not.

This code will change the current page to SecondPage, where the template code from BasicPage already makes sure, that the SecondPage will display a BackButton at the left top:

private void btnGotoSecondPage_Click_1(object sender, RoutedEventArgs e)
{
    this.Frame.Navigate(typeof(SecondPage));
}

image image

Categories: Metro, Windows 8

Windows 8 App Setttings flyout dialog

September 8, 2012 1 comment

All Windows 8 app settings must be accessible through the same mechanism.
While in any app, the user must be able to enter the settings dialog through the settings charm. (Swipe from the right edge on a touch device or use WinKey+C)

The settings charm by default will display the generic settings dialog like this one on the left.

The user can follow links from this dialog to specific settings, which in turn will display another dialog.  This other dialogs will always lay on top of the current dialog,
so it seems, that they are replacing it.
The only difference is, that this other dialogs have a back button
on the top, which allows the user to go back to the initial settings page.

image image

Clicking on anything outside the settings dialog will close the dialog (light dismiss).

Sample dialog after clicking on "My Settings menu" entry

Adding a new menu entry to the default settings page

To add a settings dialog, the first step is to add a menu label to the default settings page.

For this the CommandsRequested event must be intercepted, e.g. by adding the hilighted line in the ctor of the Mainpage:

This will make sure, that the new settings menu label will be added to the settings pane, before the pane will be shown. 
The Microsoft UI style guide recommends to use either a 346 px or 646 px wide dialog for the settings flyout!

private double settingsWidth = 346; // should be 346 or 646 
private Popup settingsPopup;        // container for flyout
private Rect windowBounds;          // determine correct height
public MainPage() { this.InitializeComponent(); windowBounds = Window.Current.Bounds; SettingsPane.GetForCurrentView().CommandsRequested +=
SettingsOnCommandsRequested;
Window.Current.SizeChanged += OnWindowSizeChanged; } void OnWindowSizeChanged(object sender,
Windows.UI.Core.
WindowSizeChangedEventArgs e) { windowBounds = Window.Current.Bounds; }
void SettingsOnCommandsRequested(SettingsPane settingsPane,
SettingsPaneCommandsRequestedEventArgs eventArgs) { UICommandInvokedHandler mySettingsHandler
=
new UICommandInvokedHandler(onSettingsCommand); SettingsCommand mySettingsCommand
=
new SettingsCommand("MySettingsId", "My Settings menu",
mySettingsHandler); eventArgs.Request.ApplicationCommands.Add(mySettingsCommand); }

 

Then we also need a handler, which gets executed, when the user clicks the new settings menu. This handler will then create a popup dialog on top of the settings pane, in which the settings flyout page will be added. The folllowing code does exactly this:

 

void onSettingsCommand(IUICommand command)
{
// Create a Popup window which will contain our flyout. settingsPopup = new Popup(); settingsPopup.Closed += OnPopupClosed; Window.Current.Activated += OnWindowActivated; settingsPopup.IsLightDismissEnabled = true; settingsPopup.Width = settingsWidth; settingsPopup.Height = windowBounds.Height; // Add the proper animation for the panel. settingsPopup.ChildTransitions = new TransitionCollection(); settingsPopup.ChildTransitions.Add(new PaneThemeTransition() { Edge = (SettingsPane.Edge == SettingsEdgeLocation.Right) ? EdgeTransitionLocation.Right : EdgeTransitionLocation.Left }); // Create a SettingsFlyout the same dimenssions as the Popup. SettingsFlyout mypane = new SettingsFlyout(); mypane.Width = settingsWidth; mypane.Height = windowBounds.Height; // Place the SettingsFlyout inside our Popup window. settingsPopup.Child = mypane; // Let's define the location of our Popup. settingsPopup.SetValue(Canvas.LeftProperty,
SettingsPane.Edge == SettingsEdgeLocation.Right ?
(windowBounds.Width - settingsWidth) : 0); settingsPopup.SetValue(
Canvas.TopProperty, 0); settingsPopup.IsOpen = true;
}

 
Then we need to make sure, that clicking outside the dialog will automatically close the dialog. This can be done by handling the Activated event and checking for Deactivated state.

Then make sure, that when the dialog really gets dismissed, that the Activated event handler gets removed:

private void OnWindowActivated(object sender, 
                Windows.UI.Core.WindowActivatedEventArgs e)
{
    if (e.WindowActivationState == 
          Windows.UI.Core.CoreWindowActivationState.Deactivated)
    {
        settingsPopup.IsOpen = false;
    }
}


void OnPopupClosed(object sender, object e)
{
    Window.Current.Activated -= OnWindowActivated;
}

..

 

Now clicking on the new menu entry, the system will display the SettingsFlyout.xaml page inside the settings pane.

This page is a regular "Basic page", inheriting from LayoutAwarePage.

Make sure to set the design width attribut to either 346 or 646 so that the designer also displays it in correct way.

The XAML should look like this:

 

<common:LayoutAwarePage
    x:Class="FlyOutSampleApp.Views.SettingsFlyout"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:common="using:FlyOutSampleApp.Common"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="768"
    d:DesignWidth="346">

The the real content of the settingspage must then be added to Row 1 of the LayoutRoot grid:

<ScrollViewer VerticalScrollBarVisibility="Auto" Grid.Row="1">

<
Grid Margin="40,33,40,39" VerticalAlignment="Top" Grid.RowSpan="3">
<
StackPanel x:Name="FlyoutContent">
<
TextBlock FontWeight="Bold" Text="My Settings" />
<
ToggleSwitch Name="ts1" Header="WLAN"

OnContent="ON" OffContent="OFF"

Toggled="ts1_Toggled_1" IsOn="True"/>
<!-- ... some more settings controls.. --->

</
StackPanel>
</
Grid>
</
ScrollViewer>

      


The code behind for the SettingsFlyout should have some code for setting the transitions and positions:

public SettingsFlyout()
{
    this.InitializeComponent();
    FlyoutContent.Transitions = new TransitionCollection();
    FlyoutContent.Transitions.Add(new EntranceThemeTransition()
    {
        FromHorizontalOffset = 
        (SettingsPane.Edge == SettingsEdgeLocation.Right) ? 
            ContentAnimationOffset : (ContentAnimationOffset * -1)
    });
}

 

And then finally the back button handling:

private void MySettingsBackClicked(object sender, RoutedEventArgs e)
{
    // First close our Flyout.
    Popup parent = this.Parent as Popup;
    if (parent != null)
    {
        parent.IsOpen = false;
    }

    // If app is not snapped, then back button shows Settings pane again.
    if (Windows.UI.ViewManagement.ApplicationView.Value != 
Windows.UI.ViewManagement.
ApplicationViewState.Snapped) { SettingsPane.Show(); } }
Categories: Metro, Windows 8

Windows 8 Toast Notifications

September 5, 2012 Leave a comment

Every Windows 8 New UI Style app can display notifications, which will be shown on the right top corner like this:

image

User can ignore or close the messages using the Close symbol.

If the user clicks on the message, the the app will be invoked again and the code in app.xaml – OnLaunched() will be executed

 

Display toast notification

To display a notification the following code is needed:

  1. Fetch one of the predefined templates as XML:
    XmlDocument xmlDoc = 
        ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText02);
    
    // ToastTemplateType.ToastText02 will return xml like this:
    //<toast>
    //  <visual>
    //    <binding template="ToastText02">
    //      <text id="1"></text>
    //      <text id="2"></text>
    //    </binding>
    //  </visual>
    //</toast>
    

  2. Update the toast data:
    XmlDocument xmlDoc = 
        ToastNotificationManager.GetTemplateContent
    (
    ToastTemplateType.ToastText02); // ToastTemplateType.ToastText02 will return xml like this: //<toast> // <visual> // <binding template="ToastText02"> // <text id="1"></text> // <text id="2"></text> // </binding> // </visual> //</toast>

  3. Get a ToastNotifier and show the notification:

    ToastNotifier toastNotifier = 
    ToastNotificationManager.CreateToastNotifier();
    ToastNotification toastNotification = new ToastNotification(xmlDoc); toastNotifier.Show(toastNotification);

 

Now the toast should be displayed. If not, then the user did probably disable toast notifications. This can be done either per app, globally or per user. See section below

Schedule toast notification

App can show a toast at a specific time. The app must not run at the given time.

This can be done using almost the same code as for displaying the notification. The only difference is, that a ScheduleToastNotification object must be created from the Xml.

This code will display the given notification at the specified time:

  1. Fetch one of the predefined templates as XML:
    XmlDocument xmlDoc = 
        ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText02);
    
    // ToastTemplateType.ToastText02 will return xml like this:
    //<toast>
    //  <visual>
    //    <binding template="ToastText02">
    //      <text id="1"></text>
    //      <text id="2"></text>
    //    </binding>
    //  </visual>
    //</toast>
    

  2. Update the toast data:

    XmlDocument xmlDoc = 
        ToastNotificationManager.GetTemplateContent
    (
    ToastTemplateType.ToastText02); // ToastTemplateType.ToastText02 will return xml like this: //<toast> // <visual> // <binding template="ToastText02"> // <text id="1"></text> // <text id="2"></text> // </binding> // </visual> //</toast>

  3. Get a ToastNotifier and add the scheduled notification:
  4. ToastNotifier toastNotifier = 
    ToastNotificationManager.CreateToastNotifier();
    ScheduledToastNotification toastNotification =
    new ScheduledToastNotification (xmlDoc,

    new DateTimeOffset(DateTime.Now.AddSeconds(5)));

    toastNotifier.AddToSchedule(toastNotification);

 

Checking the notification setting


There are many possible ways to disable notifications. It can be done on user, app or global level. The current setting and the possible values can be fetched using this code:

var setting = ToastNotificationManager.CreateToastNotifier().Setting;
switch (setting)
{
    case NotificationSetting.DisabledByGroupPolicy:
        break;
    case NotificationSetting.DisabledByManifest:
        break;
    case NotificationSetting.DisabledForApplication:
        break;
    case NotificationSetting.DisabledForUser:
        break;
    case NotificationSetting.Enabled:
        break;
    default:
        break;
}

Categories: Metro, Windows 8

Windows 8 Secondary Tiles

September 5, 2012 Leave a comment

User can invoke a function of your program to create a secondary tile on the startscreen.

This can be used to directly jumping into a specific context of your app. If the user clicks on this secondary tile, then the provided startup argument will be provided to the OnLaunch event. Pinning and unpinning can only be done through the user and cannot be fully automated.

The user always must fill out a small dialog and then click OK to pin a secondary tile.

Sample dialog:

image

 

To pin a secondary tile, the following code is needed:

Uri logo = new Uri("ms-appx:///Assets/SecondaryTile.png");

SecondaryTile secondaryTile = 
    new SecondaryTile(SECONDARY_TILE_ID,
                        "Title text...",
                        "text for search in start screen",
                        "arguments for startup",
                        TileOptions.ShowNameOnLogo,
                        logo);

bool isPinned = await secondaryTile.RequestCreateAsync();

Removing a secondary tile can be done manually by the user itself or from code:

SecondaryTile secondaryTile = new SecondaryTile(SECONDARY_TILE_ID);
bool isRemoved = await secondaryTile.RequestDeleteAsync();

Categories: Metro, Windows 8

Windows 8 Advanced Tile & Badge Topics

September 2, 2012 Leave a comment

Scheduled TileNotification

Tile data can not only be marked with an expiration date, it’s also possible to attach a timestamp for the first display. For this the class ScheduledTileNotification must be used instead of TileNotification.

Creation of a ScheduledTileNotification needs the same xmlData as with TileNotification, but allows to attach the timestamp for the initial display.

As with TileNotication, it is also possible to attach an expiry timestamp.
Then instead of calling .Update() the AddToSchedule() method must be called

Example:

ScheduledTileNotification scheduledTileNotification =
new ScheduledTileNotification(xmlDoc, deliveryTime);


scheduledTileNotification.ExpirationTime =
new DateTimeOffset(DateTime.Now.AddSeconds(35)); // Get a TileUpdater and perform the update TileUpdater tileUpdater = TileUpdateManager.CreateTileUpdaterForApplication(); tileUpdater.AddToSchedule(scheduledTileNotification);

 

Note: A maximum of 4096 notifications can be scheduled

Clearing and removing notifications:

Scheduled notifications can be removed and retrieved using GetScheduledTileNotifications() and RemoveFromSchedule()

 

Periodic Tile Notification

Update of tile data can also be automated to the system, which then fetches the data periodically from a source in the internet. The uri must return data in one of predefined XML-formats, where the placeholders are already filled with real data.

Example data:

<tile>
  <visual>
    <binding template="TileSquareBlock">
      <text id="1">Head</text>
      <text id="2">Data from Internet: 14:42:00: detail</text>
    </binding>
  </visual>
</tile>

Example code:

TileUpdater tileUpdater = 
TileUpdateManager.CreateTileUpdaterForApplication();
tileUpdater.StartPeriodicUpdate(
new Uri(http://www.stanglmayr.de/TileData.xml),
PeriodicUpdateRecurrence.HalfHour);

 

There is also an option to provide a timestamp for the initial start and the refreshinterval can be one of the following options:



image

 

.StopPeriodicUpdate() will stop the automatic refresh.

 

 

Periodic Badge Notification

The same methode can be used for fetching badge data from any internet source, whioch must provide the data in any of this predefined formats:

Example data:

<badge value="95"/>


Example code:

BadgeUpdater badgeUpdater = 
BadgeUpdateManager.CreateBadgeUpdaterForApplication(); badgeUpdater.StartPeriodicUpdate(
new Uri(http://www.stanglmayr.de/BadgeData.xml),
PeriodicUpdateRecurrence.HalfHour);

Categories: Metro, Windows 8