| Comments

Recently I’ve been writing a few XAML Behaviors for Callisto and looking to take some contributions on this front as well.  One thing that I realized is that this will bring in a new dependency for my toolkit.  I’m still trying to figure out if I want to do that or not, but that’s not what this post is about.  My #1 consumers of Callisto are using the NuGet package.  I also distribute Callisto through the Visual Studio gallery as an Extension SDK. 

What’s the difference you ask?

Extension SDK vs. NuGet package

While not an official answer, this is my basic definition I always describe to people.  It is not complete comparing all features but defines what I see as the core difference between the two.

An Extension SDK is installed per-machine and allows you to install it once and use for multiple projects.  It is deployed through the Visual Studio extensions mechanism (VSIX) which has a feature that allows for you to be notified if a version is updated in the IDE.  This is a proactive update that even if you just have VS open you get a little toast if any of your extensions are updated…very handy.  Extension SDKs also have some cool features about enabling you to supply design-time assets that don’t ship with your application and also provide some nice per-architecture deployment capabilities rather easily.  Extensions SDKs have great support for native projects as well.

NOTE: People sometimes confuse VSIX == Extension SDK.  VSIX is a packaging and installer mechanism, not an SDK only.  You can have a VSIX that deploys a tool, templates or an SDK. 

A NuGet package is installed per-project when added as a reference to your project in Visual Studio.  You can add them similarly through the “Add Reference” type dialogs (although in VS it is called Manage NuGet References) and once you select your package it is installed (per the package’s manifest instructions) into your project.  If you want to use the package for multiple projects, you must repeat this step for each project.  One benefit of the NuGet route is that it does become a part of your project, you can check it in to source control, etc.  One disadvantage currently is it doesn’t do the design-time aspects and the per-architecture deployment aspects well.

You might look at these differences and wonder why you would want to take a dependency on a per-machine item in a per-project package.  And you’d be right to ask that question.  Again, I’m still wondering myself.  However one thing to note is some Microsoft-delivered SDKs are delivered shipped with Visual Studio as Extension SDKs, as is the case with the Behaviors SDK.  So you can’t have VS installed without it, but NuGet also can be used in non-VS scenarios as well.  This can be complex depending on your package/needs.  For mine, this might be acceptable.

Telling your NuGet package to include an Extension SDK

I admit that this title is a bit misleading, but allow me to explain first.  NuGet allows for you to extend the package install a bit by including a PowerShell script to run during install (and uninstall) of the package.  This script can give you context of 4 things in your project/tools environment: install path (where the package is being installed), tools path (the folder where the script will actually reside), package (the NuGet package object) and project (a reference to the IDE Project instance).  It is this last piece that helps you manipulate the project structure.

In Visual Studio 2012 a new interface was added to the VS project extensibility to accommodate automating adding Extension SDKs.  This new interface, References2, includes a new method AddSDK.  This is the hook where you can add Extension SDKs.

NOTE: The other methods of Add() are still supported and would allow you to add references to files, GAC assemblies, etc.

The AddSDK has 2 parameters but only one is required, the identifier of the Extension SDK (it is weird to me that the first param is optional but oh well).  The ID of the Extension SDK is the name of the SDK (as defined by the deployed folder or the ProductFamilyName in the SDKManifest.xml) combined with the version number.  A final string to pass in the second parameter of AddSDK is then something like:

BehaviorsXamlSDKManaged, version=12.0

Now that we know this format we can add this to our NuGet install PowerShell script.  Here’s an example of what one might look like:

param($installPath, $toolsPath, $package, $project)
$moniker = $project.Properties.Item("TargetFrameworkMoniker").Value
$frameworkName = New-Object System.Runtime.Versioning.FrameworkName($moniker)
Write-Host "TargetFrameworkMoniker: " $moniker
if ($frameworkName.Version.Build -ge 1)
{
    Write-Host "Adding Behaviors SDK (XAML)"
    $project.Object.References.AddSDK("Behaviors SDK (XAML)", "BehaviorsXamlSDKManaged, version=12.0")
}

Notice the first line with the param() function.  Per the NuGet documentation this is required to get the environment objects like $project.  Now in line 8 we have a reference to the VSProject, then can get at its object model, get to the references and add one to an Extension SDK, in this case the Behaviors SDK installed with Visual Studio 2013.

The tricky thing with this approach is that when someone were to remove a package you may be tempted to remove the SDK reference as well.  Since there is not really good tracking whether someone may be using the reference, it is advised against that approach.  Your app developer may be using that Extension SDK now outside of your package and you have no reliable way of knowing that.  What you can do is alert the developer during uninstall:

param($installPath, $toolsPath, $package, $project)
Write-Host "Callisto was removed, however Blend SDK (XAML) was not
 as it may be a dependent reference on other things in your project.
  If you do not need it, manually remove it."

Not awesome, but helpful at least to output some data to the developer.

Summary

Again, while this may be unconventional and some NuGet purists will scoff at the mere suggestion of doing something like this, it is good to know this is easily available.  My goal is to help developers (including myself) and if there are ways to merge these two worlds of Extension SDKs and NuGet packages until (if?) they unify then by all means I love helping make my productivity better.

Hope this helps anyone!

| Comments

I’m continuing in my series of helping to provide Callisto migration tips to use new Windows 8.1 features. In a recent post I talked about the Flyout control and provided the path to the platform-provided features. In Callisto, the Menu control was provided as sort of a prescribed content for the Flyout control. In fact you really couldn’t use Menu without Flyout.

Menu control sample image

This guide will help you change to the platform-provided MenuFlyout now available in Windows 8.1.

API Differences

On the public surface area, there aren’t actually many changes here. Windows 8.1 MenuFlyout provides more functionality as it derives from FlyoutBase, which is the base for Flyout as well. So you get the same ShowAttachedFlyout capability that you have there. Both have an Items property that is a collection of the menu items you’d put in there. For these purposes I’m not detailing out the minutiae of differences between FlyoutBase and Menu here as it isn’t relevant to migration but is useful later as I’ll demonstrate. The main reason is that as I noted earlier, you actually can’t use Menu in Callisto without using Flyout, hence the lack of a significant delta here at the Menu level.

Change to the MenuFlyout

As with the other examples, I’m going to use the Callisto test app code here to show migration. Since Menu needed Flyout, you had more of a code-focused approach in ideal Callisto usage. We believe that the main use cases for Menus are also in Button invoke scenarios. Here’s an example of showing a Menu in Callisto:

private void ShowFlyoutMenu(object sender, RoutedEventArgs e)
{
    Callisto.Controls.Flyout f = new Callisto.Controls.Flyout();
    f.PlacementTarget = sender as UIElement;
    f.Placement = PlacementMode.Top;
    f.Closed += (x, y) =>
    {
        LogEvent("Event: Closed");
    };
 
    Menu menu = new Menu();
 
    MenuItem mi = new MenuItem();
    mi.Tag = "Easy";
    mi.Tapped += ItemClicked;
    mi.Text = "Easy Game";
    mi.MenuTextMargin = new Thickness(28, 10, 28, 12);
 
    MenuItem mi2 = new MenuItem();
    mi2.Text = "Medium Game";
    mi2.Tag = "Medium";
    mi2.Tapped += ItemClicked;
    mi2.MenuTextMargin = new Thickness(28, 10, 28, 12);
 
    ToggleMenuItem tmi = new ToggleMenuItem();
    tmi.Text = "Enable Logging";
    tmi.IsChecked = chk;
    tmi.Tapped += (a, b) =>
        {
            chk = !chk;
        };
 
    menu.Items.Add(mi);
    menu.Items.Add(mi2);
    menu.Items.Add(new MenuItemSeparator());
    menu.Items.Add(new MenuItem() { Text = "Foobar something really long", Tag = "Long menu option", MenuTextMargin = new Thickness(28,10,28,12) });
    menu.Items.Add(tmi);
 
    f.HostMargin = new Thickness(0); // on menu flyouts set HostMargin to 0
    f.Content = menu;
    f.IsOpen = true;
}

You will have to understand some of the events and variables are examples here (LogEvent and chk). Notice how you have to create a Flyout first, then put the Menu in it with all the items. Here is how you would migrate that code to provide immediate migration to the platform control:

private void ShowMenuFlyout3(object sender, RoutedEventArgs e)
{
    MenuFlyout mf = new MenuFlyout();
    MenuFlyout.SetAttachedFlyout(sender as FrameworkElement, mf);
    mf.Closed += (x, y) =>
        {
            LogEvent("Event: Closed");
        };
 
    MenuFlyoutItem mi = new MenuFlyoutItem();
    mi.Tag = "Easy";
    mi.Tapped += ItemClicked;
    mi.Text = "Easy Game";
 
    MenuFlyoutItem mi2 = new MenuFlyoutItem();
    mi2.Text = "Medium Game";
    mi2.Tag = "Medium";
    mi2.Tapped += ItemClicked;
 
    ToggleMenuFlyoutItem tmi = new ToggleMenuFlyoutItem();
    tmi.Text = "Enable Logging";
    tmi.IsChecked = chk;
    tmi.Tapped += (a, b) =>
        {
            chk = !chk;
        };
 
    mf.Items.Add(mi);
    mf.Items.Add(mi2);
    mf.Items.Add(new MenuFlyoutSeparator());
    mf.Items.Add(tmi);
 
    MenuFlyout.ShowAttachedFlyout(sender as FrameworkElement);
}

Now notice how the shape of the items is similar so helping with some migration. You create a MenuFlyout, MenuFlyoutItems (notice the separator and ToggleMenuFlyoutItem), then add them to the MenuFlyout and show it. But just like Flyout in Windows 8.1 we believe there was an easier way we could provide creating and using MenuFlyout.

A better way to use MenuFlyout

Much like Flyout we believe the primary use case for MenuFlyout will be from ButtonBase invocations. Let’s look at the declarative approach to the code above:

<AppBarButton Icon="Add" Label="New Game">
     <AppBarButton.Flyout>
         <MenuFlyout>
             <MenuFlyoutItem Tag="Easy" Text="Easy Game" Tapped="ItemClicked" />
             <MenuFlyoutItem Tag="Medium" Text="Medium Game" Tapped="ItemClicked" />
             <MenuFlyoutSeparator />
             <ToggleMenuFlyoutItem Text="Enable Logging" IsChecked="True" />
         </MenuFlyout>
     </AppBarButton.Flyout>
 </AppBarButton>

This allows us to provide an automatic way to show the menu when the button is clicked. If we aren’t using a Button we can still use the Set/ShowAttachedFlyout method as demonstrated above.

Summary

Moving to the new MenuFlyout control will again gain you better performance, compliance with UI guidelines, declarative model and accessibility features. As you can see there is a short-term migration approach using the the ShowAttachedFlyout method to allow you to very quickly take advantage of the new control if you were using the Callisto code method. Your app can then decide if it makes sense to move to the declarative model. Either way, the new control is great and you should use it! We also have a Windows 8.1 MenuFlyout SDK Sample that you can examine to play around with the API.

Hope this helps!

| Comments

This is another post in my series of providing migration tips from certain Callisto controls to using Windows 8.1 features. I previously demonstrated probably the most popular Callisto control, the SettingsFlyout. Coming in a very close second in popularity is the Flyout control. The Flyout is a concept of a non-modal small dialog for information and commands.

Flyout sample image

The primary use case for a lot of Flyouts was something from Button areas, namely the AppBar. Getting the experience right was not intuitively easy using a Popup primitive as you had to handle the right UI guidelines for animation, positioning and dismiss logic. Callisto provided most of this in the Flyout class but also left some people wanting a bit more flexibility. This post will aim to help you migrate existing Callisto Flyout code to the new Windows 8.1 Flyout class.

API Differences

As I did with showing some of the more prominent API differences in SettingsFlyout, I’m presenting some of the important differences for Flyout here. You should read this table as Callisto API==old, Windows 8.1 API==new and what you should use.

Callisto APIWindows 8.1 APIComments
HorizontalOffset/VerticalOffsetn/aNot really needed in almost all default cases. If you really needed to adjust the default logic, you could provide a template for FlyoutPresenter and change the margin there.
HostMarginn/aNot needed
HostPopupn/aNot needed
IsOpenShowAttachedFlyoutSee explanation below
PlacementPlacementSame concept, different enum
PlacementTargetShowAttachedFlyoutSee explanation below
ClosedClosed
n/aOpenedNew event
n/aOpeningNew event

Changing your code – an example

Similar to previous examples, I’m going to use the Callisto test app examples here. Flyout in Callisto was another control that didn’t work well in markup. This section will show how you would change your existing code if you were using the Callisto method to use the new Flyout in Windows 8.1. After this section I’ll explain a better way to do this for most cases and the preferred way to use the control. However again I want to provide a “least code change” mechanism to migrate and will do so here.

In Callisto, you most likely wrote code to trigger opening a Flyout. Here’s an example taken from the test app (this was from a Button click event):

private void ShowFlyoutMenu2(object sender, RoutedEventArgs e)
{
    Callisto.Controls.Flyout f = new Callisto.Controls.Flyout();
 
    // content code removed for brevity
    // assume "b" variable here represents a visual tree or a user control
    f.Content = b;
 
    f.Placement = PlacementMode.Top;
    f.PlacementTarget = sender as UIElement;
    
    f.IsOpen = true;
}

The code here basically requires you to wire this up in an event handler and provide the UIElement as the PlacementTarget so it knows where to position the Flyout.

To change this here is what it would look like in Windows 8.1:

private void ShowFlyoutMenu2(object sender, RoutedEventArgs e)
{
    Flyout f = new Flyout();
 
    // again for brevity sake assume "b" here represents content
    f.Content = b;
 
    Flyout.SetAttachedFlyout(sender as FrameworkElement, f);
    Flyout.ShowAttachedFlyout(sender as FrameworkElement);
}

The key here is the SetAttachedFlyout/ShowAttachedFlyout method calls. You must first attach the Flyout to the FrameworkElement (again in this case this is on a Button). Then you show it. I’ve omitted the Placement here to allow for the new default (top) to occur. You could have also added Placement to the change as well. Placement will attempt to fit in this order: Top, Bottom, Left, Right.

The above is meant to demonstrate how to quickly change from Callisto code with minimal impact. The next section actually shows a preferred way of using the control and what a lot of Callisto users were actually asking for.

A better way to use Flyout

As demonstrated the Flyout can still be called from code after attaching it to a FrameworkElement. You are then responsible for calling the ShowAttachedFlyout method to open it. The Windows 8.1 Flyout was designed for the primary use case of ButtonBase elements and will automatically show for you when used in those cases. Let’s assume an example where I have a Button in my AppBar (btw, you should use the new AppBarButtons in Windows 8.1) and I want to show a Flyout when the user clicks on the button. I could do the event model above, but my MVVM friends are cringing a bit. Here’s an alternate and the most likely way you would use Flyout:

<AppBarButton Icon="Add" Label="Add File">
    <AppBarButton.Flyout>
        <Flyout>
            <!-- content here -->
        </Flyout>
    </AppBarButton.Flyout>
</AppBarButton>

As you can see here, on Button we’ve provided an attached property to put the Flyout element and its content. The framework will handle the showing of the Flyout when automatically attached to the Button like this. If you don’t want to use the Button method and perhaps you have to launch a Flyout from some other UIElement, you would use the ShowAttachedFlyout method as demonstrated above.

Summary

As one of the more popular controls this migration may take you down the quick route first and then give you more time to think about using the declarative way to really change later. I recommend using the new Flyout here as you will get all the proper behavior as well as better performance, accessibility and interaction with the software keyboard. We also have a new Windows 8.1 Flyout SDK Sample that walks through this usage and some other scenarios you can examine for your needs.

Hope this helps!

| Comments

Continuing on my tips in migrating from Callisto for platform-supported Windows 8.1 APIs, I’ll cover another simple, but helpful text control in this post: WatermarkTextBox.

WatermarkTextBox sample image

When writing an app that provides input from customers, providing some “hint” when there is no text is a valuable thing to add. Here’s how to change to the platform-supported APIs.

Change back to TextBox

When using Callisto, you had to use a specific control that derived from TextBox. Simple enough:

<callisto:WatermarkTextBox Watermark="Enter some text..." />

In Windows 8.1 the concept of watermark text was added to controls for text input, including PasswordBox (one of the requests Callisto frequently got in this area). This support is added via the PlaceholderText property on these controls. The use is simple and to change from Callisto, simply move back to TextBox control and use the property:

<TextBox PlaceholderText="Enter some text..." />
<PasswordBox PlaceholderText="Enter your password" />

There are some subtle UI differences here in that the PlaceholderText in Windows 8.1 is not italic (something I personally prefer to better differentiate), but that’s about it. The same functionality of when it shows and doesn’t exists.

Summary

A quick change to your code will yield you yet another gain of removing a sub-classed control with it’s own template and take advantage of platform-supported text goodness and performance. Make the change my friends, make the change! Be sure to check out the other Callisto migration tips when moving your app to Windows 8.1!

Hope this helps!

| Comments

Frankly I’m going to be honest and say I’m not sure why it took us so long to add this capability to TextBlock, especially given that the support in Callisto provided via DynamicTextBlock was originally done in Silverlight 2. O_O. Well, Robby can rest well now knowing that we no longer have to depend on his contributions to Callisto.

DynamicTextBlock sample image

Example of use DynamicTextBlock on bottom

Here’s the quick migration tip.

Change back to TextBlock

The DynamicTextBlock served one purpose, to provide trimming at the character level rather than the word level. The implementation of DynamicTextBlock was done using a ContentControl which, frankly, was probably too heavy handed for the usage here. However since TextBlock is sealed this was necessary. The usage for having this was simple:

<callisto:DynamicTextBlock Text="Some long text here" TextWrapping="NoWrap" />

And changing this to provide platform-supported trimming is simple as well:

<TextBlock Text="Some long text here" TextTrimming="CharacterEllipsis" />

Yep, that’s it.

Summary

This migration should be quick and painless. Using the platform’s TextBlock will allow you to benefit from the new typography settings provided in Windows 8.1 (like TextTrimming=”Clip” as well) in conjunction with this as well as better global text support. I’m thankful we were able to add this into the platform finally.

Hope this helps!