Talk to the View


There are many scenarios where a UI component might not have a Command or bindable property available for certain features that you need to access from the view model. There is a simple, but powerful, thing you can do to allow this and not break MVVM or testing capability, leverage the Interface.

Scenario

Let’s imagine the scenario where we have a special ListView control that has a HighlightItem method that can only be called with a direct reference to that control. There isn’t a Command or DependencyProperty (aka BindableProperty in Xamarin.Forms) alternative, so it has to be done in the code behind.

To keep this simple, here’s the page XAML…

<Page x:Class="MyPage">
    <Page.DataContext>
        <MyPageViewModel x:Name="ViewModel" />
    </Page.DataContext>

    <SpecialListView x:Name="MyListView" />
</Page>

…and here is the page code behind.

public partial class MyPage : Page
{
    public MyPage()
    {
        InitializeComponent();

        // The only way to use HighlightItem method is in the code-behind
        MyListView.HighlightItem(itemToHighlight);
    }
}

As you can see, the HighlightItem method has to be used in the code behind because it has a reference to ‘MyListView’. However, you need to use it in the view model, like this:

public class MyPageViewModel
{
    private void PleaseHighlightItemNow()
    {
        // But, you need to highlight the item from view model
    }
}

Solution

One solution for this is to define an interface.

public interface IHighlightableView
{
    void Highlight(object item);
}

With this, you can add a property to the view model and invoke the method:

public class MyPageViewModel
{
    public IHighlightableView View { get; set; }

    private void PleaseHighlightItem()
    {
        // Call the method on the interface!
        View?.Highlight(itemToHighlight);
    }
}

Now, the interface can be implemented on the page to complete the circle

public partial class MyPage : Page, IHighlightableView
{
    public MyPage()
    {
        InitializeComponent();

        // Assign this page instance to the view model
        ViewModel.View = this;
    }

    private void Highlight(object itemToHighlight)
    {
       // Now you can directly use the UI component's method
        MyListView.HighlightItem(itemToHighlight);
    }
}

Summary

This is a simple approach that will work if you don’t want to (or are not allowed to) use an existing MVVM framework’s built-in DependencyInjection and IoC features. Enjoy!

Easy XamlCompositionBrushBase

The upcoming Windows 10 update, the Fall Creator’s Update, introduces a new design system, Microsoft Fluent Design System. The design system has 5 major building blocks:

  • Light
  • Depth
  • Motion
  • Material
  • Scale

You can use any of these in a multitude of ways, however Microsoft has made it very easy to use in the latest Preview SDK (16190). Some of the things that used to be relatively hard, or at the least verbose, can now be done with a few lines of code.

Today, I want to show you the XamlCompositionBrushBase (aka XCBB). Before I do, let’s briefly run through a XAML Brush and a Composition Brush.

The XAML Brush

We use Brushes in almost everything we do, they paint the elements in an application’s UI. For example, UIElement.Foreground and UIElement.Background both are of type Brush.

The most commonly used Brush is the SolidColorBrush, an example of setting the Foreground brush:

XAML

&lt;TextBlock x:Name=&quot;myTextBlock&quot; Foreground=&quot;Black&quot;/&gt;

C#

myTextBlock.Foreground = new SolidColorBrush(Colors.Black);

There are other brush types, such as ImageBrush, that are good for specific approaches, that make our live easier because it would otherwise require more work to achieve the same result.

The Composition Brush

A composition brush utilizes the relatively new Composition layer in Windows 10. This layer sits underneath the XAML layer where all your XAML elements live. You can do a lot with the composition layer, animations, effects and more. The mechanism that paints Composition layer elements also uses a “Brush”, however it’s a type of Composition Brush and cannot be used with your XAML directly.

XamlCompositionBrushBase

With the release of the 16190 preview SDK, you can now use the Composition layer and XAML layer together by using the XamlCompositionBrushBase!

This is BIG news because the XCBB allows for interoperability between the Composition layer and the XAML layer and lets you set up composition effect without needing to implement a behavior or other more advanced setups. As an example, let’s create a Brush that applies the Win2D Invert Effect,

Note: I wanted to keep this as simple as possible to focus on XCBB, you can expand on this with more complex Effects, such as the GaussianBlur here.

First, let’s example the XCBB’s two methods that you want to override:

  • OnConnected
  • OnDisconnected

So, here’s our starting point:

public class InvertBrush : XamlCompositionBrushBase
{
    protected override void OnConnected()
    {
        // Set up CompositionBrush
        base.OnConnected();
    }

    protected override void OnDisconnected()
    {
        //Clean up
        base.OnDisconnected();
    }
}

Now, for the awesome part… the XCBB has a CompositionBrush property! All you need to do is instantiate your effect. Here’s the completed Brush code and I’ve broken it down to the important steps:

public class InvertBrush : XamlCompositionBrushBase
{
    protected override void OnConnected()
    {
        // Back out if it's not ready yet
        if (CompositionBrush == null) return;

        // 1 - Get the BackdropBrush
        // NOTE: BackdropBrush is what is behind the current UI element (also useful for Blur effects)
        var backdrop = Window.Current.Compositor.CreateBackdropBrush();

        // 2 - Create your Effect
        // New-up a Win2D InvertEffect and use the BackdropBrush as it's Source
        var invertEffect = new InvertEffect
        {
            Source = new CompositionEffectSourceParameter("backdrop")
        };

        // 3 - Get an EffectFactory
        var effectFactory = Window.Current.Compositor.CreateEffectFactory(invertEffect);

        // 4 - Get a CompositionEffectBrush
        var effectBrush = effectFactory.CreateBrush();

        // and set the backdrop as the original source
        effectBrush.SetSourceParameter("backdrop", backdrop);

        // 5 - Finally, assign your CompositionEffectBrush to the XCBB's CompositionBrush property
        CompositionBrush = effectBrush;

    }

    protected override void OnDisconnected()
    {
        // Clean up
        CompositionBrush?.Dispose();
        CompositionBrush = null;
    }
}

Now that the Brush’s definition is complete, how do we actually use it? This is the most exciting part… you use it like any other Brush in XAML!


&lt;Grid&gt;
    &lt;Grid.Background&gt;
        &lt;brushes:InvertBrush /&gt;
    &lt;/Grid.Background&gt;
&lt;/Grid&gt;

Showtime

Here’s an example implementation. I have an Ellipse with an ImageBrush and it’s currently showing Tuvok (full disclosure: I’m a Trekkie AND a Star Wars fan)

&lt;Ellipse x:Name=&quot;ImageEllipse&quot;&gt;
    &lt;Ellipse.Fill&gt;
        &lt;ImageBrush ImageSource=&quot;{Binding SelectedCharacter.ImagePath}&quot; Stretch=&quot;UniformToFill&quot; /&gt;
    &lt;/Ellipse.Fill&gt;
&lt;/Ellipse&gt;

Sketch (2)

If I put another matching Ellipse using my custom InvertBrush on top of the Tuvok Ellipse, here’s the result:


&lt;Ellipse x:Name=&quot;ImageEllipse&quot;&gt;
    &lt;Ellipse.Fill&gt;
        &lt;ImageBrush ImageSource=&quot;{Binding SelectedCharacter.ImagePath}&quot; Stretch=&quot;UniformToFill&quot; /&gt;
    &lt;/Ellipse.Fill&gt;
&lt;/Ellipse&gt;
&lt;Ellipse&gt;
    &lt;Ellipse.Fill&gt;
        &lt;strong&gt;&lt;brushes:InvertBrush /&gt;&lt;/strong&gt;
    &lt;/Ellipse.Fill&gt;
&lt;/Ellipse&gt;

Sketch (3)

Notice how it only inverted what was directly behind the Ellipse and not the page background or the drop shadow?

Level Up

In the case of the InvertEffect, we don’t have any effect variables to update, so there’s no need for a DependencyProperty to set initial values of the effect. However, in most cases, you will need a DependencyProperty in your XCBB to tweak the effect’s values.

To see this, look at the BackdropBlurBrush example here and notice how the Blur.BlurAmount effect property can be updated by using a ScalarParameter when calling CreateEffectFactory.

I hope I was able to clarify how easy it is to get started using the XCBB and how this makes things easier for XAML devs to get the benefits of working with the Composition layer without doing a lot of work.

Happy coding!

Lance

One XAML for UWP, Windows 8.1 and Windows Phone 8.1

I was recently involved in a conversation on how to have the easiest way to maintain a XAML view across a UWP (Universal Windows Project) a Windows 8.1 and Windows Phone 8.1 projects. There are a few options and the most straight forward way to do it with a UserControl residing in a Portable Class Library. However…

What if you wanted to have tailored code for each without littering your code with #ifdef but still share a XAML view?  The XAML View might be what you’re looking for. This is a tutorial on how to do just that. An example project is available for download at the end of the article. Let’s get started:

Step 1:

Create a new 8.1 Universal app

tpx1

Step 2:

Move the Shared, Windows and Windows Phone projects out of the virtual folder and delete the folder (you can cut/paste or just click and drag them). The solution should look like this now

tpx2

(Note: If you’re doing this to a solution that has many other projects, you might want to skip this step and add the UWP project to the virtual folder instead)

Step 3:

Add a new UWP project to the solution and name it the same as the 8.1 app, but with the Universal suffix.

tpx3

(Your solution should look like this now)

tpx4

Step 4:

Add a “Views” folder to each of the projects

tpx5

Step 5:

Within the Universal project, right click and Add > New Item > XAML View

tpx6

Step 6:

Move the new XAML View to the Shared project’s Views folder and change the namespaces in the view to match

tpx7

Step 7:

Delete App.xaml from the Universal project and add a reference to the solution’s Shared project (Note: this is in the new Shared projects references section)

tpx8

Step 8:

Here’s where the magic happens. We’ll be adding a code behind for this view in each of the projects! I’ll break this down into sub-steps:

  1. Add a new class to the Windows 8.1 project’s Views folder (Add > New Item), name it as if it were the code-behind for the view. In this case it would be SharedPage.xaml.cs
  2. Change the namespace of the class to Views
  3. Add the public, sealed and partial modifiers to the class
  4. You’ll next need to inherit from the Page class
  5. Add a page constructor
  6. Now you can copy and paste this new class into each of the platform projects (remember, we do not need it in the Shared project)

This is what it should look like

tpx9

Step 9:

You’ll need to quickly pop into the Build Configuration Manager and check off Build and Deploy for the Universal app (you can find Configuration Manager in the target dropdown or in the Build menu)

tpx10

Step 10:

Lastly, for the purposes of this demo, go to App.xaml.cs and change the initial launch target (MainPage) to be the new shared page (SharedPage). I could have put a button on MainPage for each app, but let’s keep this tutorial as short as possible.

tpx11

Final result!

This is the same XAML View compiled with different code-behind files 🙂

tpx12

(NOTE: I put a TextBlock on the SharedPage and update the text in each constructor to show which platform launched it. Here are the WP8.1 emulator, Windows 10 PC and Windows 10 Mobile Emulator running their apps all showing the same XAML view).

Source Code

Download the Sample App Source Code From Here

Bonus:

The Telerik Universal Control can be used in the shared page as long as each of the projects have a reference to the Telerik UYI for Windows Universal DLLs. Send me a tweet and show me what you’ve done, I’ll RT your awesomeness!

Custom Pivot Header with Animation

I recently wanted to make a header with tabs for my app’s pages that have a Pivot. Something like Office Mobile, but without the drop-down menus. Here’s the result I got in my upcoming app. I decided to post a tutorial and provide a sample app.

CustomPivotHeader

 

Notice the fast fade-in of the background color of the tab, this is important and is where you’ll be able to add your own flavor to the style after you’ve completed this tutorial. Ok, let’s get started!

Step One: Create the base elements

The two main components are a Pivot control and a ListView control. The Pivot has been stripped of it’s title template and pivot header templates. To get started, let’s do a File > New Pivot App (WinRT, not Silverlight) so that we’ll have some sample data and a pre-existing Pivot.

StepOne1

After the project template finishes, open PivotPage.XAML and add RequestedTheme=”Light” to the page’s properties. Next, find the root grid of the page. Add a couple RowDefinitions, with the first row’s height set to auto. Add a Grid containing a ListView to Row 0 and put the Pivot into Row 1.

StepOne2

Now, let’s clean up the pivot. Delete the Pivot’s Title and both the PivotItem’s Header properties. You should be left with only the pivot item’s contents, this is what your page should look like at this point.

StepOne3

Step Two: Create a Control for the Tabs

My demo uses text, however there are other approaches that can use an icon or other element in the tab. Since not all XAML elements have a “Foreground” property that can automatically inherit from the parent ListView’s foreground, we’ll use a  container control to hold the TextBlock. Make this by right clicking on your project and select Add > New Item. Then find Templated Control and give it the name HeaderTab.cs.

StepTwo1

A template control has a backing style where the UI is defined while the control’s logic is in the file named after it. Visual Studio will add a folder named Themes and a ResourceDictionary Generic.xaml.

StepTwo2

First, Open HeaderTab.cs and change the base class from Control to ContentControl. This will allow you to use the control as a ContentControl, which is what the ListViewItem’s template uses.

StepTwo4

Next, open Generic.xaml, ignore the errors for now, they will go away when you do a Build at the end of this step. First, replace the Border control in the style with a TextBlock. Now, use TemplateBindings for the Text and Margin properties (see screenshot). This is how we pass the properties values of the ListView ItemContainerStyle to our custom control when the property types to match. The Margin property is a perfect example, we use the padding of the container style for the margin of the TextBlock, this will make more sense towards the end of the tutorial. Okay, now it’s time to do a Build (F6) so that your style’s TargetType will resolve.

This is what your Style should look like:

StepTwo3

Step Three: Create a horizontal ItemsPanel

In order to tell the ListView to render the items horizontally, we need an ItemsPanel, however since we want the content of the tab to be in the center but also stretch to fill the available space, we can’t use a simple StackPanel. So, let’s make our own. Right click on your project and select Add > New > Class and name it HorizontalStretchPanel.

StepThree1

Explaining the process of calculating the available space and arranging the items is outside the scope of this article, but in a nutshell, we take the full width and divide it by the number of items then arrange to get the most space for each item. Here’s the code to copy/paste:


public class HorizontalStretchPanel : Panel
{
protected override Size ArrangeOverride(Size finalSize)
{
var rect = new Rect(0, 0, finalSize.Width, finalSize.Height);
var width = finalSize.Width / Children.Count;

foreach(var tab in Children)
{
rect.Width = width;
rect.Height = tab.DesiredSize.Height &gt; finalSize.Height ? tab.DesiredSize.Height : finalSize.Height;
tab.Arrange(rect);
rect.X = width + rect.X;
}

return finalSize;
}

protected override Size MeasureOverride(Size availableSize)
{
if(Children.Count == 0)
return base.MeasureOverride(availableSize);

var finalSize = new Size { Width = availableSize.Width };
availableSize.Width = availableSize.Width / Children.Count;

foreach(var tab in Children)
{
tab.Measure(availableSize);
var desiredSize = tab.DesiredSize;
finalSize.Height = desiredSize.Height &gt; finalSize.Height ? desiredSize.Height : finalSize.Height;
}

if(double.IsPositiveInfinity(finalSize.Height) || double.IsPositiveInfinity(finalSize.Width))
return Size.Empty;

return finalSize;
}
}

 

Step Four: Create a ListView Configuration and ItemContainerStyle

Now it’s time to go back to the ListView we added to the top of PivotPage.xaml . Before working on the ListView, Give the parent Grid a height of 50 and a good background that will contrast with white, I went with Blue. Now, onto the ListView. Let’s set the ListView.ItemsPanel to use our new HorizontalStretchPanel. Next, add some ListViewItems containing your new HeaderTab control. You’ll want one ListViewItem for each PivotItem you have. While you’re there, set the FontSize of your HeaderTab to 20.

Now, bind the SelectedIndex of the ListView to the SelectedIndex of the Pivot using an ElementName binding and set VerticalAlignment to bottom.

Here’s what it should look like thus far

StepFour1

Now, it’s time to add some style and animation to the ListViewItemContainer. To begin, extract the ListView’s default ItemContainerStyle, this screenshot shows how:

StepFour2

Give a name, I chose HeaderListViewItemContainerStyle, once you click Ok, the ListView will get a StaticResource reference to the style in the page’s Resources. Scroll up to the top of the page and expand the style. Yeah, it’s pretty long. the part I want you to get to is the Template property. Within here you’ll see some animations, but go past them until you see the ContentControl. This is what shows your HeaderTab control, I like to give my template parts names with strong prefixes, you don’t have to, but it’s easier for identification when it comes to animation.

Now, let’s edit that template to add an extra Grid so we can act on it to get some cool fading animation when the user changes tabs. What we’re going to do is put the new Grid behind the ContentControl so that we don’t block the Text. To make this easier, here is what the XAML looks like after renaming the parts and adding the Grid.

StepFour3

Lastly, I went with White for the Style’s foreground property, this gets inherited by the TextBlock in your HeaderTab control. It will contrast well against the Blue background of the page header Grid.

Step Five: Animating the Container’s Parts

This is something that you’ll want to play with and where Blend can help you get the exact results you’re looking for. What we’re going to do is add some keyframes to the existing States: UnselectedSelected and SelectedFocused. Here’s where the string naming of the template parts comes in handy. First, in the Unselected state we want to style it they way we want it to look when the tab is not in focus. In this state I want my new Grid to have zero height. Here’s what that looks like:

StepFive1

Now let’s go to the Selected and SelectedFocused states (they’re the same in my scenario). In this state I want the new Grid to be the full height of the tab and more importantly to have a white background.

StepFive2

Lastly, the sugar that adds the magic… the transition animation. The cool thing about states is that you don’t have to write long storyboards, just set a Default Transition for a particular state. You can add these right to the VisualStageGroups directly (don’t forget to add some Easing). Here’s what it looks like

StepFive3

 

Almost done! Go through the Pivot and PivotItems and delete all the x:UID properties, these will change your UI at runtime because of localization, best to get them out of the way now. Whew! now it’s time to fire up the emulator and take it for a spin. This is what you should be seeing, if not, download the sample app from here and see what went wrong.

Happy coding!

FinalDemoResult

 

Invalid XAML error updating from WP7

We are now seeing the beginning of the fast decline of Windows Phone 7 as it exits the market over the next several months, many of you will need to act to update your app to at least Windows Phone 8.  I did this for all of my WP7 apps and there was one error that was In just about every upgrade:

An error on this XAML namespace declaration:

xmlns:controls="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls"

Previous to Windows Phone 8, the Pivot and Panorama controls were part of a toolkit. The Windows Phone team did a solid by included these in the OS, they also added new controls like the LongListSelector to replace the toolkit’s ListPicker . These controls are now found in the Phone namespace.

It’s a very frustrating problem if you’re seeing it for the first time. Don’t worry, there is a really easy fix… Delete the xmlns:controls line and use only the xmlns:phone one or edit it and remove the “.Contols” part of the assembly pointer. Here is what it will look like after doing the edit option:

xmlns:controls="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"

However, in many newer app templates, this is already used for the xmlns:phone declaration that looks like this:


xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"

If you do have the xmlns:phone declaraiton, simply delete the bad line xmlns:controls line and change any UI controls on the page to use the phone one instead. For example

Change:

<controls:Pivot x:Name="MyPivot"> foo </controls:Pivot>

to

<phone:Pivot x:Name="MyPivot"> foo </phone:Pivot>

I hope this blog post was found when you searched for the error and it fixed it for you 🙂 Let me know if this doesn’t fix it for you and I’ll take a look at your XAML.

Happy coding!

Denied?

So, you got an email from DVLUP stating that your challenge submission was denied.  Why were you denied? What did you miss?  I wanted to write this post to share the top reasons for denial and how to fix it… 90% of these are due to the fact you didn’t edit your WMAppManifest file.

Here are the top offenders:

  • Not all Live Tiles Sizes
  • No animated Tiles
  • Not all WP8 resolutions

#1- You need to have all three tile sizes enabled for your app. Here is a list of the tile sizes from the MSDN Documentation. To rectify this problem, simply toggle the “Support for large Tiles” property in your WMAppManifest file. See the image in answer #2 for more details.

Tile Sizes

#2- Your app failed because the tiles were static. You need to bring your pinned tiles to life with one of the tile templates. Below is an example, find more here in the MSDN Documentation:

Cyclic Template– This template rotates between 1 to 9 images for your pinned tile. To meet the challenge’s requirement you need to have at least 2 images. Here is a quick and easy way to setup a tile from an event handler:


CycleTileData cycleTile = new CycleTileData()
{
Title = &quot;DVLUP Rules&quot;;
Count = 2;
SmallBackgroundImage = new Uri(&quot;/Images/smallBackgroundImage.jpg&quot;, UriKind.Relative);

// An array of URIs will do the trick
CycleImages = new Uri[]
{ // You can have up to 9 images
new Uri(&quot;/Images/cycleImage1.jpg&quot;, UriKind.Relative),
new Uri(&quot;/Images/cycleImage2.jpg&quot;, UriKind.Relative),
new Uri(&quot;/Images/cycleImage3.jpg&quot;, UriKind.Relative),
new Uri(&quot;/Images/cycleImage4.jpg&quot;, UriKind.Relative),
new Uri(&quot;/Images/cycleImage5.jpg&quot;, UriKind.Relative),
new Uri(&quot;/Images/cycleImage6.jpg&quot;, UriKind.Relative),
new Uri(&quot;/Images/cycleImage7.jpg&quot;, UriKind.Relative),
new Uri(&quot;/Images/cycleImage8.jpg&quot;, UriKind.Relative),
new Uri(&quot;/Images/cycleImage9.jpg&quot;, UriKind.Relative),
}
};

Another way to setup the Cyclic Template is directly in your WMAppManifest file by assigning an image directly like this:

2012-12-13_1150

#3- Your app needs to support all three Windows Phone resolutions. This link will take you to the MSDN documentation on how to target different resolutions. Here is a screenshot of the new resolutions for Windows Phone from the docs and also my WMAppManifest file.

2012-12-13_1143

2012-12-13_0927

Great, now you’re armed with the information you need to resubmit your application. Update your app through DevCenter, once it’s live in the Store go back into DVLUP and resubmit the app to the challenge. If you have any questions, send me an email to ext-lance.mccarthy(at)nokia(dot)com.