Change XAML designer background color in Visual Studio

If you use the Visual Studio 2013 XAML designer with the light theme enabled and you are designing user controls or pages with transparent backgrounds, it might be hard to read the text:

vsbefore

Solution

One quick solution is to change the XAML UI Designer colors.

  • Click TOOLS > OPTIONS… > Environment > Fonts and Colors
  • Under Show settings for choose XAML UI Designer
  • Change Item foreground and Item background to the same color to prevent a checkerboard pattern

 

vscolor

Now you can read your text again:

vsres

Cross platform development with C#

phoneAre you writing apps for multiple platforms? Do you wonder what you can and cannot share when writing C# for Windows Phone, Windows 8 and WPF?

Me and Christian Lang tell you all about it! We’ve prepared a great talk where you learn how to write an application and convert it to a multi-targeted app. The goal is to write native apps that respect the UI paradigms and capabilities of the platform, while sharing as much of the code as possible in the Business and Data layer:

share

We talked & coded at the .NET user group here in Berlin:

cross

And we will do it again at Spartakiade (March 23, 2014) and at Developer Week 2014 (July 14-17, 2014) in Nürnberg.

Interested?

Come see us talk about Cross Platform development with C# at Spartakiade in Berlin or Developer Week in Nürnberg. Can’t make it? Send me an email (loek@6wunderkinder.com) to discuss the possibilities to talk at your company!

First aid for detecting memory leaks in a Windows Store App

fix-water-leak-reno-lg1Before submitting your Windows 8 app to the Windows Store, it never hurts checking for memory problems. This article is about detecting these problems in an early stage of development. I’ll show you a super easy trick to do this without the need for memory profilers. The solution is to put a TextBlock on each page that shows the memory currently in use. The good thing is that after a while you get an understanding about how much memory your app “should use”. If this changes suddenly, you are in a good position to guess why it happened and the solution is only one Git-action away.

Showing memory usage on your page

  • Put this TextBlock in your MainPage.xaml
<TextBlock TextWrapping="Wrap" x:Name="mem" FontSize="21.333"/>
  • And add the following code to your OnNavigatedTo event handler in MainPage.xaml.cs:
mem.Text = "Memory in use: " + Math.Round(GC.GetTotalMemory(true) / 1000000.0, 2) + "mb";

Now see what happens if I navigate between 2 pages in my app. Watch the MEMORY USE text in the left upper corner:

mem

Clearly my app has a major memory leak. If your memory increases with 1 MB each time you navigate, older pages are probably not garbage collected.

Meten is weten!

Indicating memory leaks is as simple as adding 2 lines of code to each page. It will help you to get a good feeling of memory usage regardless of problems.

Choosing a specific master page for each Windows Store App page

At 6Wunderkinder we are creating the Windows Store Version (WinRT) of Wunderlist. Our app basically has two kinds of pages. One is where you are logged in and one is where you are not logged in. We use a master page to take care of backgrounds and other stuff that is shared across pages. When all pages are the same, you just replace Window.Current.Content as Frame (in App.xaml.cs) with your master page (as described by Fons Sonnemans) and load all other pages within that masterpage. But what if you want to support multiple masterpages?

master

Well, it turns out it is very easy to do this and you can even use the default Frame from App.xaml.cs.  Download a demo project or follow the next steps to create Application Navigation where pages can use a specific masterpage or no masterpage at all!

Step 1: Create a Masterpage

  • Create a new blank page (MasterPage.xaml) that acts as a masterpage. You can include some app-wide xaml like this:
<Page
    x:Class="MasterPageTest.MasterPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="#FF363333">
        <Grid.RowDefinitions>
            <RowDefinition Height="43*"/>
            <RowDefinition Height="213*"/>
        </Grid.RowDefinitions>
        <TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" Text="Master!" VerticalAlignment="Center" FontSize="48" Margin="100,0,0,0"/>
        <TextBox HorizontalAlignment="Center" x:Name="search" TextWrapping="Wrap" Text="TextBlock1" VerticalAlignment="Center" FontSize="18.667" Width="200"/>

        <Frame x:Name="ContentFrame" Content="Frame" Grid.Row="1" Margin="100"/>

        <StackPanel Margin="0,0,100,0" Orientation="Horizontal" HorizontalAlignment="Right">
            <Button Content="MainPage" Click="ButtonBase_OnClick1" HorizontalAlignment="Center" VerticalAlignment="Center" Width="150" Height="80" Margin="0"/>
            <Button Content="Second Page" Click="ButtonBase_OnClick2" HorizontalAlignment="Center" VerticalAlignment="Center" Width="150" Height="80" Margin="0"/>
            <Button Content="Logout" Click="ButtonBase_OnClick3" HorizontalAlignment="Center" VerticalAlignment="Center" Width="150" Height="80" Margin="0"/>
        </StackPanel>
    </Grid>
</Page>

Don’t worry about the Button Click Handlers. We will implement them later. Important in the code above is the placeholder for your content:

<Frame x:Name="ContentFrame" Content="Frame" Grid.Row="1" Margin="100"/>

Step 2: Create a navigation helper

  • Add the class NavigateService.cs to your project and enter this code:
    public class NavigateService
    {
        private static readonly Lazy<NavigateService> lazy = new Lazy<NavigateService>(() => new NavigateService());
        public static NavigateService Instance { get { return lazy.Value; } }

        public Frame Frame { get; set; }

        public void Navigate(Type pageType)
        {
            Frame.Navigate(pageType);
        }

        public void Navigate(Type pageType, Type masterPageType)
        {
            var masterPage = Frame.Content as Page;
            if (masterPage != null && masterPage.GetType() != masterPageType)
            {
                Frame.Navigate(masterPageType);
                masterPage = Frame.Content as Page;
            }
            var contentFrame = masterPage.FindName("ContentFrame") as Frame;
            contentFrame.Navigate(pageType);
        }
    }

Step 3: Assign the rootFrame to the NavigationService

  • Open App.xaml.cs and the OnLaunched method with:
protected override void OnLaunched(LaunchActivatedEventArgs e)
        {
            Frame rootFrame = Window.Current.Content as Frame;
            if (rootFrame == null)
            {
                rootFrame = new Frame();
                Window.Current.Content = rootFrame;
            }

            NavigateService.Instance.Frame = rootFrame;

            if (rootFrame.Content == null) {
                rootFrame.Navigate(typeof(LoginPage), e.Arguments);
            }
            Window.Current.Activate();
        }

Step 4: Add click handlers to navigate

  • Open Masterpage.xaml.cs and add the following handlers:
private void ButtonBase_OnClick1(object sender, RoutedEventArgs e)
{
  NavigateService.Instance.Navigate(typeof(MainPage),  typeof(MasterPage));
}
private void ButtonBase_OnClick2(object sender, RoutedEventArgs e)
{
  NavigateService.Instance.Navigate(typeof(SecondPage), typeof(MasterPage));
}
private void ButtonBase_OnClick3(object sender, RoutedEventArgs e)
{
   NavigateService.Instance.Navigate(typeof(LoginPage));
}

You will get some errors because you don’t have a SecondPage.xaml and LoginPage.xaml yet.

  • Create SecondPage.xaml and put a page title on it so you will recognize it once loaded in the masterpage.
  • Open MainPage.xaml and put a title on that also
  • Create Login.xaml and enter the following XAML:
<Grid>
    <Button Content="Login" Click="ButtonBase_OnClick"   HorizontalAlignment="Center" VerticalAlignment="Center" Width="200" Height="100"/>
</Grid>
  • Open LoginPage.xaml.cs and add the following handler:
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
   NavigateService.Instance.Navigate(typeof(MainPage), typeof(MasterPage));
}

Now run your code and you will see that the Login page uses no masterpage and the other pages share Masterpage.xaml.

This is a very basic masterpage navigation system. For our app we extended it with viewmodel injection. If you need help with that, just email me!

Save XAML as PNG in a Windows Store App

Do you want to create thumbnails, attachments or other bitmappy representations of your XAML? Very good. After reading this tutorial, you will know how to save any XAML-thingy as a PNG and save it to ApplicationData.Current.LocalFolder. And as a bonus, you will learn how to avoid the infamous UnauthorizedAccessException, caused by the image being used by the <image> control.

Grab the demo code here.

Untitled

Step 1: Save XAML as PNG

To save XAML as a PNG, use the following method:

private async Task SaveImage() {
            var renderTargetBitmap = new RenderTargetBitmap();
            await renderTargetBitmap.RenderAsync(text);
            var pixelBuffer = await renderTargetBitmap.GetPixelsAsync();

            var file = await ApplicationData.Current.LocalFolder.CreateFileAsync("text.png", CreationCollisionOption.ReplaceExisting);

            using (var stream = await file.OpenAsync(FileAccessMode.ReadWrite)) {
                var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream);
                encoder.SetPixelData(
                    BitmapPixelFormat.Bgra8,
                    BitmapAlphaMode.Ignore,
                    (uint)renderTargetBitmap.PixelWidth,
                    (uint)renderTargetBitmap.PixelHeight, 96d, 96d,
                    pixelBuffer.ToArray());

                await encoder.FlushAsync();
            }
        }

The XAML (the text variable is a TextBox) is now saved to the LocalFolder. If you want to check this, go to c:\users\loek\appdata\local\packages and search for text.png. A folder with a GUID-like name will pop up and there you will find the image.

Step2: Showing the image

To show the image in an Image control, you could just point the ImageSource attribute to ms-appdata:///local/text.png but a funny thing will happen the second time you try to write to the file. You will get an UnauthorizedAccessException.

Appearently the Image control keeps the PNG locked so what we will do is get the file as a stream:

private async Task LoadImage() {
            var file = await ApplicationData.Current.LocalFolder.GetFileAsync("text.png");
            var stream = await file.OpenAsync(FileAccessMode.Read);
            var bitmapImage = new BitmapImage();
            await bitmapImage.SetSourceAsync(stream);
            image.Source = bitmapImage;
        }

This will keep the PNG file unlocked and you can overwrite it as many times as you want. Windows 8.1 made it really easy to save XAML as a PNG and I hope this tutorial helped you!