Archive

Archive for August, 2012

Windows 8 Tile Badges

August 31, 2012 Leave a comment

This is a follow up post to my last one, which was Windows 8 Tile Notifications.

Badges are another nice way, to display application data on the start tile.

There are two different sets of badges:

– Numbers, which can be in the range from 0..99
            (with larger values the display will remain at 99, 0 will clear the display at all)

– Glyphs, which can be one of 12 predefined icons, see here

Both sets appear in the lower right corner of a tile, either on top of the standard tile or any other custom tile data.

Badges can be used pretty much the same way as Tiles. The following code fragments are need for enabling Badges:

  1. Fetch one of the predefined templates as XML: (Number or Glyph)
    XmlDocument xmlDoc = 
    BadgeUpdateManager.GetTemplateContent(BadgeTemplateType.BadgeNumber);

    XmlDocument xmlDoc = 
    BadgeUpdateManager.GetTemplateContent(badgeTemplateType); // using BadgeTemplateType.BadgeNumber or .BadgeGlyph will return: // <badge value=""/>

  2. Update the badge value

  3. var node = xmlDoc.SelectSingleNode("/badge");
    node.Attributes[0].NodeValue = badgeValue;
    

    .

  4. Get a BadgeUpdater and perform the update

    BadgeNotification badgeNotification = new BadgeNotification(xmlDoc);
    BadgeUpdateManager.CreateBadgeUpdaterForApplication()
    .Update(badgeNotification);

  5.  

      Clearing badge values and expiration is done the same way as tiles

        BadgeUpdateManager.CreateBadgeUpdaterForApplication().Clear();
        BadgeNotification badgeNotification = new BadgeNotification(xmlDoc);
        badgeNotification.ExpirationTime 
        =
        new DateTimeOffset(DateTime.Now.AddSeconds(10));

        Categories: Metro, Windows 8

        Windows 8 Tile Notifications

        August 30, 2012 Leave a comment

        Windows 8 enables to display app specific data without starting the app.

        This mechanism can be used in many different ways.

        Using Windows Notification Service

        One way is to use the Windows Notification Service, which pushes updates to the tile. This requires, that the device is connected to the internet and that there is a app specific server side logic running, which acts as the source for the update.

        Windows Notification Service then will act as a gateway and forward this messages to the device and its app tile.

        I plan to describe the needed steps in a later post. First let’s see, how we can update the tile from with in the app itself.

         

        Using local TileUpdateManager, during app runtime

        An app can push data to the tile, whenever its running.

        For this, the following code is needed:

        1. Fetch one of the predefined templates as XML:
          XmlDocument xmlDoc = 
          TileUpdateManager.GetTemplateContent(TileTemplateType.TileSquareBlock); // using TileTemplateType.TileSquareBlock will return the following xml: //<tile> // <visual> // <binding template="TileSquareText01"> // <text id="1"></text> // <text id="2"></text> // </binding> // </visual> //</tile>

           

        2. Update the tile data

          var
          text1Node = xmlDoc.SelectSingleNode("//text[@id='1']");

          var
          newText1 = xmlDoc.CreateTextNode(headerText);

          text1Node.AppendChild(newText1);
          var text2Node = xmlDoc.SelectSingleNode("//text[@id='2']");
          var newText2 = xmlDoc.CreateTextNode(DateTime.Now.ToString("HH:mm:ss")
          +
          ": " + detailText);
          text2Node.AppendChild(newText2);

        3. Get a TileUpdater and perform the update

          TileNotification tileNotification = new TileNotification(xmlDoc);
          TileUpdater tileUpdater = TileUpdateManager.CreateTileUpdaterForApplication();
          tileUpdater.Update(tileNotification);

        Now the tile update should be visible within seconds…

         

         

         

        Manually removing custom tile data

        All updates to a tile stay visible until another update overwrites them. To reset the tile to the initial state, a call to Clear() will help:

        TileUpdateManager.CreateTileUpdaterForApplication().Clear();

         

         

         

        Using expiration to revert to the initial tile data


        tileNotification.ExpirationTime =
        new DateTimeOffset(DateTime.Now.AddSeconds(10));

         

         

        Create Queue of Updates

         

        Up to 5 tile notifications can be scheduled and the system will automatically rotate between this notifications. If more notifications will be added, then only the last 5 updates will be visible. Older notifications will be discarded.

         

        To enable this queue behavior, the following code is needed:

        TileUpdateManager.CreateTileUpdaterForApplication()
        .EnableNotificationQueue(
        true);

        // Get a TileUpdater and perform the update

        TileUpdater tileUpdater =
        TileUpdateManager.CreateTileUpdaterForApplication();
        for (int i = 0; i < 5; i++)
        {
        TileNotification tileNotification
        = GetTileData(
        "H"+ (i+1),"Scheduled: "
        + (i+1)); tileUpdater.Update(tileNotification);
        }
          

        Categories: Metro, Windows 8

        Using UserControls in Windows Store Apps

        August 30, 2012 Leave a comment

         

        When having the need for the same UI in multiple places inside an app, it probably makes sense to exctract that UI to a single place and reuse UI and code behind in multiple places.

        In this sample we have multiple pages with this content:

            <Grid Grid.Row="1" Margin="120,0,0,0">
                <StackPanel Width="300" HorizontalAlignment="Left">
                    <TextBlock Text="Edit item" Style="{StaticResource SubheaderTextStyle}" />
                    <TextBlock Text="Title:" />
                    <TextBox Text="{Binding Title, Mode=TwoWay}" />
        
                    <TextBlock Text="Text:" />
                    <TextBox Text="{Binding Text, Mode=TwoWay}" />
                </StackPanel>
            </Grid>
        <

         

        The only difference for the multiple instances of this UI template code is the caption text, which should be a variable.

        To create a variable we need to follow this steps:

        1. Add a new item of type “UserControl” to the project, place it into a directory Controls
        2. Move the <Grid> into this usercontrol
        3. Create the variable parts with binding to a property in the code behind, here CaptionText
        4. Instead of using the DataContext, which is inherited from the host page, we set the target to the control itself by using the syntax ElementName=<NameOfTheControl>, here “MyUserControl”
        5. The usercontrol will then look like this:

        <UserControl
            x:Class="SimpleApp.Controls.EditControl"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="using:SimpleApp.Controls"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            mc:Ignorable="d"
            d:DesignHeight="300"
            d:DesignWidth="600"
            x:Name="MyUserControl">
        
            <Grid Grid.Row="1" Margin="120,0,0,0">
                <StackPanel Width="300" HorizontalAlignment="Left">
                    <TextBlock Text="{Binding CaptionText, ElementName=MyUserControl}" Style="{StaticResource SubheaderTextStyle}" />
                    <TextBlock Text="Title:" />
                    <TextBox Text="{Binding Title, Mode=TwoWay}" />
        
                    <TextBlock Text="Text:" />
                    <TextBox Text="{Binding Text, Mode=TwoWay}" />
                </StackPanel>
            </Grid>
        </UserControl>

        1. In the usercontrol code behind create a property, in this example named CaptionText
        2. In the ctor register a DependencyProperty with optional change handlers
              public sealed partial class EditControl : UserControl
              {
                  public EditControl()
                  {
                      this.InitializeComponent();
                      CaptionTextProperty = DependencyProperty.Register("CaptionText", typeof(string),
                      typeof(EditControl), new PropertyMetadata("", OnTextChanged));
                  }
          
                  public static DependencyProperty CaptionTextProperty { private set; get; }
          
                  public string CaptionText
                  {
                      set { SetValue(CaptionTextProperty, value); }
                      get { return (string)GetValue(CaptionTextProperty); }
                  }
          
                  static void OnTextChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
                  {
                      (obj as EditControl).OnTextChanged(args);
                  } 
          
                  void OnTextChanged(DependencyPropertyChangedEventArgs args)
                  {
                  }
              }
        3. Now use the usercontrol in any page
        4. Add a xmlns:uc=”using MyApp.Controls” statement to all the pages, where this new usercontrol should be used.

          MyApp.Controls must match the namespace used in the usercontrol

           <uc:EditControl Grid.Row="1" CaptionText="Add new item"/>
        Categories: Metro, Windows 8

        Windows 8 Metro Style App Development with XAML and C#

        August 9, 2012 Leave a comment

        Updated for VS 2012 RTM

        In this post i will show how to create a small app, which can be used to add, edit or delete small notes. The app will use the MVVM concept, where all the data is stored in the Viewmodel and data binding is used to synchronize data and views.

        The app allows to edit or add notes, where each note contains a few properties like Last Update, Title and text

        At the end of all the steps the app should look like this:

        image image

        My recommended steps for creating a new app with VS 2012:

        Step 1: Create the base app

        1. Create new App based on the Split App (XAML) template
          (I’m using this, because the “Blank App” template is missing some template code)

          image

        2. Remove all XAML-Pages, but not the App.xaml
        3. Create new folders named Pages, Model and ViewModel
        4. Add a new Page to Pages folder named MainPage based on “Basic Page” item template
        5. Change all references in App.xaml.cs from ItemsPage to MainPage
        6. Remove x:Key=AppName in MainPage and update corresponding entry in App.xaml
        7. In MainPage add a new GridView to row 1 of the existing toplevel grid (LayoutRootStyle)
        8. Starting the app should now show a blank page with only the app name at the top

          image

        Step 2: Adding Model and ViewModel classes

        1. Add a new classfile Note.cs to the Model folder, which derives from BindableBase
          (See Common folder)
          public class Note : BindableBase
          {
              private DateTime lastUpdate;
              public DateTime LastUpdate
              {
                  get { return lastUpdate; }
                  set { this.SetProperty(ref lastUpdate, value); }
              }
          
              private string title;
              public string Title
              {
                  get { return title; }
                  set { this.SetProperty(ref title, value); }
              }
          
              private string text;
              public string Text
              {
                  get { return text; }
                  set { this.SetProperty(ref text, value); }
              }
          }
        2. Add MainViewModel class to ViewModel folder, based on BindableBase
          public class MainViewModel : BindableBase
          {
              public ObservableCollection<Note> Notes
              {
                  get;
                  set;
              }
          
          
              public MainViewModel()
              {
                  if (Windows.ApplicationModel.DesignMode.DesignModeEnabled)
                      GenerateDesignTimeData();
              }
          }
        3. Add static property ViewModel of type MainViewModel to App.xaml.cs

          sealed partial class App : Application
          {
              private static MainViewModel viewModel; 
              public static MainViewModel ViewModel 
              { 
                  get 
                  { 
                      if (viewModel ==null) 
                          viewModel = new MainViewModel(); 
                      return viewModel;  
                  } 
                  
                  set 
                  { 
                      viewModel = value; 
                  }  
              } 

        4. Add Designtime data generation to MainViewModel ctor

          public class MainViewModel : BindableBase
          {
              public ObservableCollection<Note> Notes
              {
                  get;
                  set;
              }
          
              public MainViewModel()
              {
                  if (Windows.ApplicationModel.DesignMode.DesignModeEnabled)
                      GenerateDesignTimeData();
              }
          
              private void GenerateDesignTimeData()
              {
                  Notes = new ObservableCollection<Note>();
                  for (int i = 0; i < 50; i++)
                  {
                      Notes.Add(new Note()
                      {
                          LastUpdate = DateTime.Now.AddMinutes(-150),
                          Title = "Designtime Sample data title " + i,
                          Text = "Designtime Sample data text " + i,
                      });
                  }
              }
        5. Comment out all references to 
          – DefaultViewModel,

          – DefaultViewModelProperty,

          – IObservableMap and

          – ObservableDictionary in Common\LayoutAwarePage.cs

        Step 3: Enable display of designtime data

        1. Remove Datacontext statement from MainPage.xaml

        2. Add this to the header of MainPage.xaml, but adjust the namespace

          image

        3. Set GridView ItemsSource to {Binding Notes} and adjust Margin
        4. Define ItemTemplate and Bind to the properties of the Note classimage

        5. Now the designtime data should be visible in VS designer

          image

         

        Step 4: Load data at runtime

        1. Open App.xaml.cs and add the call to the data loading function from inside OnLaunch:

          image

           

        2. Implement dummy data loading in MainViewModel.LoadData(): 

          internal void LoadData()
          {
              Notes = new ObservableCollection<Note>();
              for (int i = 0; i < 50; i++)
              {
                  Notes.Add(new Note()
                  {
                      LastUpdate = DateTime.Now.AddMinutes(-150),
                      Title = "Runtime Sample data title " + i,
                      Text = "Runtime Sample data text " + i,
                  });
              }
          }
        3. Set DataContext = App.ViewModel in ctor of MainPage 
        4. Starting the app should now display the dummy data

          image

        Step 5: Navigate with selected item to detail page

        1. A click on any entry should display the edit page with the selected item

        2. Therefore add a new page named EditPage of type BasicPage to the pages folder
        3. Remove Datacontext statement from EditPage.xaml
        4. Add this to the header of EditPage.xaml, but adjust the namespace and note, that we are binding the page in design mode to the first entry of the designtime dummy data.
        5. (See Binding Notes[0])image

        6. Now add the following properties to the GridView in MainPage:

          image

           

        7. Add the new property SelectedNote to the MainViewModel:
          private Note selectedNote; 
          public Note SelectedNote 
          { 
              get { return selectedNote; } 
              set { this.SetProperty(ref selectedNote, value); } 
          }
        8. The statement SelectedItem={Binding SelectedNote, Mode=”TwoWay”} will set SelectedItem in the viewmodel and we just need to navigate to the EditPage
          private void GridView_ItemClick_1(object sender, ItemClickEventArgs e)
          {
              App.ViewModel.SelectedNote = (Note)e.ClickedItem;
              this.Frame.Navigate(typeof(EditPage), null);
          }

           

        Step 6: Display selected item on detail page

         

          1. Open EditPage.xaml.cs and set DataContext to App.ViewModel.SelectedNote in ctor
          2. This enables now to bind UI elements to the properties of a single Note:

            For this add a Grid to row 1 of the existing root grid and paste in the following UI elements:

            image

          3. The app should now allow to navigate to the EditPage and display the selected note:



            image

        Step 7: Add AppBar to EditPage

        1. To update the selected note, a “Save” button must be added to the bottom AppBar by adding this to EditPage.xaml:

          image

        2. This Style definition must be added to App.xaml
        3. <Style x:Key="SaveAppBarButtonStyle" TargetType="Button" 
          BasedOn="{StaticResource AppBarButtonStyle}"> <Setter Property="AutomationProperties.AutomationId" Value="SaveAppBarButton"/> <Setter Property="AutomationProperties.Name" Value="Save"/> <Setter Property="Content" Value=""/> </Style>

        4. This will place the Save button to the bottom right corner like this:

          image

        5. The click event handler will then navigate back to the MainPage:
          private void btnSave_Click_1(object sender, RoutedEventArgs e)
          {
              if (this.Frame.CanGoBack)
              {
                  this.Frame.GoBack();
              }
          }

          Now changes should be visible on MainPage after pressing Save!

        Step 8: Implement “Add Note” functionality

        1. Adding new notes will be done with the add Button in the bottom AppBar:

          image

        2. Add a new page “AddPage to the pages folder
        3. Remove Datacontext statement from AddPage.xaml and add this, but update the namespace:



          image

        4. In the AppBar AddButton click handler navigate to the AddPage:
          btnAdd_Click_1(RoutedEventArgs e)
          {
              Frame.Navigate(typeof(AddPage)); 
          }

        5. Add the same UI as in EditPage
        6. In the AddPage ctor set DataContext to a new instance of Note()
        7. Add the same Save AppBarButton as in the EditPage
        8. In the Save Button click handler add the new note to the Notes collection of App.ViewModel
          private void btnSave_Click_1(object sender, RoutedEventArgs e)
          {
              App.ViewModel.Notes.Add((Note) DataContext); 
              if (this.Frame.CanGoBack) 
              { 
                  this.Frame.GoBack(); 
              } 
          } 

         

        Step 9: Implement Process lifecycle

        need to do some some more work here…. stay tuned…

        ==========================

        Implement Process lifecycle (Suspending/resume):

        ==========================

        Add [DataContract] and [DataMember] to MainViewModel and all public members

        Add [DataContract] to BindableBase

        Add SaveViewModelData and RestoreViewModelData to App.xaml.cs and call from OnSupend / OnLaunch after termination

         .
        Categories: Metro, Windows 8

        Windows 8 XAML Introduction

        August 8, 2012 Leave a comment

        There are many ways to create Windows 8 New UI Apps. They can be based on HTML5 and Javascript or XAML and any .NET language.

        Here is a small overview, what technologies a developer can use on Windows 8 for New UI Apps:

        image

         

        In this post i’m focusing on XAML with C#. It is helpful, if you have some experience in XAML based environments like Silverlight, WPF or Windows Phone 7 (which is Silverlight).

        If you’ve never used one of this environments, no problem, just hang on.

        For my experience, the best thing to learn a technology is to use it. For this reason, i’ll walk you through the necessary steps to create a very minimalistic Windows 8 app, which we’ll then improve step by step.

        Step 1: Open VS 2012 and create a new "Windows Store" app:

        Select the Split app (XAML) template from File-New Project dialog:

        image

        Then press F5 to start the app in the debugger.

        If you do this the first time, then VS 2012 will prompt you for a Microsoft account and the password to create a free developer license for this account. This allows to create, debug and run your own created apps to run on any machine, where you are logged in with this Microsoft account.

        The app will look like this and allows to dive into any of the categories on the first page to see the linked details on the second page.

        image image

        There is already a lot of functionality in this template, which might be confusing if you are new to XAML. Therefore we’ll get rid of some parts and start from an  even simpler app:

        Step 2: Cleanup the project by removing items

        Using Solution Explorer,  remove ItemsPage.xaml and SplitPage.xaml and also the DataModel directory.

        Step 3 Add default View

        Add a new folder, named Views and add a new Page called MainPage.xaml, which is based on  the "Basic Page" template

        Open MainPage.xaml and remove <Page.Resources>….</Page.Resources>
        Open App.xaml.cs and replace ItemsPage with MainPage, make sure, that the right using is added to the top (using Ctrl-.)

        Now start the app using F5 and it should look like this:

        image

        Step 4 Adding XAML Controls

        The page already contains a Grid control, which is nested in another grid control. This divides the screen into 4 sections. This sections are defined by 2 rows and the first row is divided into 2 columns. The top row is used for the header and uses 140 px from the top. The second row is using the rest of the screen.

        image

        The <Button> control will be placed in the first row and first columns (index=0), because, there is no other Grid.Row or Grid.Column definition used with this control.
        The visibility of this button is bound to a property "CanGoBack", that is the reason, that it is not visible in the designer.

        The TextBlock control will be placed in the second column (index=1) of the first row.

        We will now add controls to the content area, which is Row=1 and Column = 0, because the second row is NOT divided into 2 columns!

         

        Step 5: Using Controls

        All XAML controls can be placed on the screen by specifying a margin attribute. This will work for some cases, but will fail if the screen size is changing or different to the developers screensize. Therefor it is not a good practice and should be avoided.

        A fluid screen layout can adapt to different screen and resolution sizes.

        There are a few different layout container controls available with XAML:

        • Grid
        • StackPanel
        • Canvas

          Grid Control

        The Grid control is the most flexible layout container which adapts very good to different screensizes and resolution. The area will be defined as set of columns and rows.
        Controls can be placed into this coordinate system and the attributes ColumnSpan and RowSpan will allow to place controls over multiple cells in the coordinate system.

        image image

         

        StackPanel Control

        StackPanel automatically places controls next to the previous control. The orientation can be either horizontal or vertical.
        See the usage of Margin to specify a left border of 120px.
        Margin attributes can be given in any of this syntax:

        Margin="30" will create a gap of 30px to every side

        Margin="30,50" will create a horizontal gap of 30 and a vertical gap of 50 px

        Margin="left,top,right,bottom" will allow to specifiy the gap for every side of the control.

        After you have the screen like it is shown below, then change Orientation to "Horizontal" for a short test!

        image  image

         

        Canvas Control

        Canvas control is the simplest container, which does not adjust the position of the new control according to the previous control. Each control must be given a margin attribute, so that it is not overlapping.

        In some scenarios it is wanted, that controls overlap, e.g. placing a rectangle around / behind another control as in this example:

        image    image

        Categories: Metro, Windows 8