Showing posts with label UWPLunch. Show all posts
Showing posts with label UWPLunch. Show all posts

Tuesday, November 08, 2016

Defining DEBUG only content in XAML

For a number of applications I've worked on, I've had content in the UI that should only be included in specific builds. Usually, I do this for the debug build but I've also done this for specific test builds too.
I've added text to make it clear that it's a specific build and I've also used this for accessing test specific content such as secret menus for impacting connectivity or for enabling test datasets.
Previously I've done this by adding named controls in the UI and then using the code-behind on the page to hide or show the content as appropriate. It's not been ideal but it's worked.
I've wanted something that was XAML only but never come up with anything appropriate. I'd looked at adding scripts at build time to control what was included based on properties or extensions in the markup but that wasn't great either.
In looking at how Xamarin.Forms works I came up with another idea.

It lets me have an app that looks like this in release mode
and like this in debug

Amazingly it's all configured in XAML
and changing the build config in VS causes the designer preview to update too.

And it only took a tiny amount of code.
enjoy.

***UPDATE***
But what about performance?

I don't think I use this enough to be concerned about the cost of having a simple extra control in the visual tree, but it's worth a little thought.
It turns out there's a simple way to achieve the same result with less code and without leaving invisible controls on the tree.
It's still not a perfect solution as this still leaves an empty content presenter lying around and does mean a line of code is executed in release builds but I think this is the best that's possible with a single code file.

Wednesday, October 19, 2016

Twitter style launch animation in XAML

All this month, I'm taking some time each day to explore (and document) things that are related to UWP development that I haven't fully investigated or used before. While doing it over lunch each day I'm calling it #UWPLunch.

Ok, so this isn't strictly tied to what's new in UWP but it's been a while since I did some animations and copying the launch animation of the Twitter app (on iOS)

The idea is simple.
An image is shown. It decreases in size briefly before growing to fill the whole screen and eventually being replaced by content.
Like this:


The face image is four paths in a canvas (not shown) and the storyboard acting on it looks like this:

<Storyboard x:Name="Storyboard" Completed="StoryboardCompleted">
    <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleX)" Storyboard.TargetName="canvas">
        <EasingDoubleKeyFrame KeyTime="0:0:0.4" Value="0.8"/>
        <EasingDoubleKeyFrame KeyTime="0:0:1.2" Value="20">
            <EasingDoubleKeyFrame.EasingFunction>
                <CubicEase EasingMode="EaseIn"/>
            </EasingDoubleKeyFrame.EasingFunction>
        </EasingDoubleKeyFrame>
    </DoubleAnimationUsingKeyFrames>
    <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleY)" Storyboard.TargetName="canvas">
        <EasingDoubleKeyFrame KeyTime="0:0:0.4" Value="0.8"/>
        <EasingDoubleKeyFrame KeyTime="0:0:1.2" Value="20">
            <EasingDoubleKeyFrame.EasingFunction>
                <CubicEase EasingMode="EaseIn"/>
            </EasingDoubleKeyFrame.EasingFunction>
        </EasingDoubleKeyFrame>
    </DoubleAnimationUsingKeyFrames>
</Storyboard>

Quite simple really.



Tuesday, October 18, 2016

App URI handlers in UWP apps - open your website with your app

All this month, I'm taking some time each day to explore (and document) things that are related to UWP development that I haven't fully investigated or used before. While doing it over lunch each day I'm calling it #UWPLunch.

If you have a website and an app you might want people navigating to your website on a device with the app installed to instead go straight to the app.

If that's what you want it's easy to do.

You just need to tell your app which website. It's just a little addition to the manifest:


Ignore the colored wiggly lines indicate that you need to declare the uap3 namespace alias:

xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"

Also add it to the IgnorableNamespaces list.

Then you tell the website about the app. Add a file named 'windows-app-web-link' to the root of the site that returns JSON like the following.

[{
  "packageFamilyName": "mrlaceycom_thnpmr8zdxbza",
  "paths": [ "*" ],
  "excludePaths" : [ "/about*" ]
 }]

When the app is Activated you can detect being launched this way by checking for activation of the kind ActivationKind.Protocol and then query the Uri to get the path that would have been viewed on the website.

You'll find more on this and another example at
https://blogs.windows.com/buildingapps/2016/10/14/web-to-app-linking-with-appurihandlers/

Monday, October 17, 2016

TreeView control for UWP apps

All this month, I'm taking some time each day to explore (and document) things that are related to UWP development that I haven't fully investigated or used before. While doing it over lunch each day I'm calling it #UWPLunch.

Many people have a good reason to require a treeview control but there isn't one included with the standard controls for the platform.
There are a few 3rd party ones but not everyone wants to use such controls.

Wouldn't it be good if Microsoft released such a control? After all, they have such a thing in their own apps.

Well, good news, such a control is coming.
There's a preview among the samples on GitHub. You'll find it at:

https://github.com/Microsoft/Windows-universal-samples/tree/dev/Samples/XamlTreeView

If you want to use it you'll need to get the whole repository because of the way some of the project files are shared amongst various samples.

It's not a simple control and it's written in C++ so that may be an issue for you but it seems pretty robust to me.
It provides customization over indentation (staggering) and whether folders can be collapsed and expanded. IT also supports the dragging of items between folders. As shown in the image here.


It can also be easily styled. And not just the icons, as below.



Thursday, October 13, 2016

Shared folders #UWPLunch

All this month, I'm taking some time each day to explore (and document) things that are related to UWP development that I haven't fully investigated or used before. While doing it over lunch each day I'm calling it #UWPLunch.

This feature has been around as long as Windows 10. I've just never used it.
You can define a folder (or folders) in an app that can also be used by other apps from the same publisher and which also know about that folder.

Be careful of copying from the docs on this topic as they contain two errors in the sample XML.
The element name is PublisherCacheFolders (with an 's')  and the Folder elements must be closed.
Like this:

  <Extensions>
    <Extension Category="windows.publisherCacheFolders">
      <PublisherCacheFolders>
        <Folder Name="Config" />
      </PublisherCacheFolders>
    </Extension>
  </Extensions>

Just add the above to Package.AppxManifest for each project.

You can then access this folder from all projects with:

StorageFolder configFolder = ApplicationData.Current.GetPublisherCacheFolder("Config");

Simples. :)

Wednesday, October 12, 2016

Single process background tasks are great - now I want a time machine #UWPLunch

All this month, I'm taking some time each day to explore (and document) things that are related to UWP development that I haven't fully investigated or used before. While doing it over lunch each day I'm calling it #UWPLunch.

On many occasions in the past, I've made lots of apps that required a level of background processing.
These were typically done by having a second project in a solution that contained a class which implemented an interface to operate as a background task.
Having the task in a separate library often led to architectural issues around how the code was divided up for sharing between the different projects for the app and the task. The juggling of code structuring and dependency issues was also further complicated when functionality necessitating a background task is added to an existing project (or one nearing the end of original development.)
It's not just the division of code that was an issue. Having the app and background task (or tasks!) communicate or share information was also an issue. Managing MutExs, locking and shared files wasn't the hardest thing in the world but it always felt like more work than should have been necessary.

All that should be a thing of the past now though as the Anniversary Update introduced single process background tasks.

A few observations that may help you:

  • The docs on MSDN seem incomplete but it really is VERY simple.
  • See the background audio sample for the best guidance.
  • You don't need to make a declaration in the package manifest to use this.
  • A network state change trigger is easy to repeatedly invoke during testing (even when not under debug) - just toggle flight mode
  • The `LeavingBackground` event is also fired when the app starts.
  • The `EnteringBackground` event is also fired when the app closes.


As the title suggests, I wish this was around years ago. It would have saved me a lot of time and effort.


Tuesday, October 11, 2016

Using the web server built into every Windows 10 device #UWPLunch

All this month, I'm taking some time each day to explore (and document) things that are related to UWP development that I haven't fully investigated or used before. While doing it over lunch each day I'm calling it #UWPLunch.

Just a few weeks ago I was thinking to myself - If Windows 10 has a built-in web server for hosting the remotely accessible device portal, can I also use it for my own functionality?
I was curious about the possibility of using any Windows10 device as my own web server.
While that's not possible, something related was announced last week and that's the Windows Device Portal Wrapper project.



This works if you enable the portal after enabling developer settings.

The idea is that it makes it an easy way for you to write an app that can interrogate the status of the device or perform some actions. The most interesting actions are probably installing or uninstalling other apps. It might provide an interesting tool for managing a small number of devices where more formal MDM solutions are too expensive or overly complex.

I'd originally wondered if this might be a route to eventually adding additional functionality to the portal but upon reflection, that's unnecessary and not the best way of doing things.

Originally I was thinking about the portal as a way to make any device a web server. But not every device needs to be a web server. If you do need a web server then forcing an arbitrary device to act as one is unlikely to lead to you getting the best results. Use tools/devices appropriate to the task.

I also wondered if the portal could become a generic way of accessing extension functionality for an installed app. I was thinking about this as a way for doing things like extracting log files from an app on a remote device. Now I'm wondering if that's too niche a task. For apps where this is appropriate, this could, I think, be achieved with a remote messaging of connected apps. (Which is something I hope to look at later this week.)

Maybe more will become possible with the portal (and the wrapper project) in the future but right now I don't see it being a part of my app dev plans.


Monday, October 10, 2016

When UWP apps targeting old or temporary SDKs can't be loaded #UWPLunch

All this month, I'm taking some time each day to explore (and document) things that are related to UWP development that I haven't fully investigated or used before. While doing it over lunch each day I'm calling it #UWPLunch.

In reviewing some UWP functionality I tried to open an old test project from earlier this year. It was a project to test some of the functionality announced at build this year. The functionality was made available at the time via a special SDK (version 14295) that wasn't an official/formal release.

When trying to open that project on my recently rebuilt PC, solution explorer shows that an update is required to load the project. Trying to download the update presents a dialog like this.

There's a problem with the install link though. It doesn't go to an SDK to download as there isn't one.
The solution was to manually modify the csproj file.









Above you can see that I've changed the TargetPlatformVersion to be the latest (AU) version and now the project can be loaded.

Ok, so this isn't something everyone will need but if you ever find yourself with an old project you can't open or get something someone has shared online and it won't open then this may help you out.


Thursday, October 06, 2016

Is Windows Mobile (Phone) still relevant?

All this month, I'm taking some time each day to explore (and document) things that are related to UWP development that I haven't fully investigated or used before. While doing it over lunch each day I'm calling it #UWPLunch.

With Microsoft doing less and less in terms of manufacturing and promoting phones running Windows 10 Mobile, many have been asking if it's a dead platform.

Obviously, it's something I think about.

Today I was at Microsoft's Transform conference. Satya Nadella (Microsoft CEO) gave the closing talk. During this he described Windows 10 as an operating system for a person across all the devices they use.



Phones are the most used and most personal devices people interact with. For Windows10 to not be a part of that would be ridiculous and I still believe that Microsoft can't abandon phones entirely.
No, they'll never be the market leader.
Yes, your mobile (phone) app strategy will need to consider building for Android and iOS. (Xamarin is, of course, a great way to do this.)
No, I don't know anything about any upcoming announcements. (And if I did I couldn't tell you.)

If you've developed for UWP or Windows Phone in the past, much of what you've learnt is hopefully still relevant regardless of the platform you're building for and UWP apps still run on desktop, Xbox, IoT, SurfaceHub, and HoloLens too.

Just keep doing as my new T-shirt says:



Wednesday, October 05, 2016

Converters are bad, so it's good that the AU means fewer are needed #UWPLunch

All this month, I'm taking some time each day to explore (and document) things that are related to UWP development that I haven't fully investigated or used before. While doing it over lunch each day I'm calling it #UWPLunch.

On the surface, converters (implementations of IValueConverter) are powerful tools but I think they're massively overused and encourage doing some things which are actually bad.

The MVVM pattern is great. It's biggest benefits are to enable code reuse and improve the ease of testing. At some point in time, many people confused the pattern and the goals as being based on not writing "code behind". Specifically, they see this as meaning there should be as little as possible code written in the XAML.cs files (ideally none.) Instead, they write more behaviors, converters, or XAML. Here's my issue. Each of these are all code (yes, even XAML) that exists in the UI layer of the app. Just like anything in the code behind file. So my first objection is that there's an artificial distinction between the file or language (XAML vs C#) that UI related code is written in.

But it goes deeper.

If I have a VM that surfaces some data that must be converted before being displayed, I've now got two classes that must be used together. This coupling makes reuse harder. I can't just move one thing around, I need to know that I need another thing with it. Unfortunately, there's no standard way of indicating the VMs dependency. (And I doubt there'd be any benefit in creating such a thing anyway.) Not only do we have two separate but related classes, the business logic for how something should be displayed has been split. This makes testing harder. There's no single item under test in this instance so tests become more complicated. That the logic is in a behavior or a converter also makes it harder to test as it can't be as easily instantiated. It's normally necessary to end up running tests on such objects via the UI. Not only are such tests harder to write they're also slower to run. (UI tests are slower to run than pure code.) Tests that are hard to write or slow to run end up being run less often and eventually abandoned, bringing less benefit and eventually none.

The overuse of something as potentially helpful as a converter can actually undo some of the benefits of the MVVM pattern.

In the past, I've hit issues with performance related to the use of converters. This should no longer be an issue unless they're doing something very complicated or you're using a very large number of them. However, it's made me wary of using them. They also run on the UI thread so can impact performance there.
Generally, I try and avoid the use of converters. Instead I move the logic into the VM itself. All nice and cozy and contained. (Don't worry, I can still encapsulate logic and avoid duplication with this.)
The biggest exception to this is for Visibility. For lots, and lots, of circumstances, it's necessary to make things visible, or not, based on specific (normally boolean) criteria. I have a converter which can take a large number of different inputs (bools, numbers, lists, strings, etc.) and turn them into a Visibility value. It's generally very useful and I use it a lot.

That may not be the case going forward though as in the Anniversary Update, compiled bindings support implicit visibility conversion for booleans.

That means you can put this in the code behind (or associated VM).

 public bool ShowMe { get; set; } = true;
 public bool DontShowMe { get; set; } = false;

And use them to control visibility like this:

 <TextBlock Text="Now you see me" Visibility="{x:Bind ShowMe}" />
 <TextBlock Text="Now you don't" Visibility="{x:Bind DontShowMe}" />

which would only display the first TextBlock.


A couple of points of note.

This only works if the minimum version of the project is the AU.
The implicit conversion only works if the app is running on a machine running the update. The above targeting means that the app will only run on such. In theory, you could include it in code that targets earlier versions and selectively include it if you can detect you're running on a machine with the update but you'd still need to support explicit conversion for when running on older machines and so would require extra code.
The other downside is that you have to bind to booleans for the code to even compile as that's all that's supported. I'll need to keep my own converter around for a bit longer to enable me to do more interesting things like hiding zero length strings or empty lists. Either that or add extra properties to the VM for binding.



Tuesday, October 04, 2016

Displaying GIFs in a UWP app #UWPLunch

All this month, I'm taking some time each day to explore (and document) things that are related to UWP development that I haven't fully investigated or used before. While doing it over lunch each day I'm calling it #UWPLunch.

Displaying GIFs in XAML apps has been notoriously tricky in the past. A mix of licensing issues and a lack of native support meant that complicated workarounds were often needed. The most common solution involved the use of an embedded webbrowser control but it was a far from ideal solution.

With the anniversary update that's changed. GIFs and even animated GIFs are now supported.

Simply drop this in a blank app.

<Image Source="https://api.giphy.com/img/giphy_search.gif" />

and get something that looks like this (minus the animation)

Going a bit further I wanted something that would show a few more animated GIFs at once so I created an app that's pointed at the giphy trending API.


It was just a case of grabbing the API response and serializing it as something suitable

    var json = await new HttpClient().GetStringAsync(new Uri("http://api.giphy.com/v1/gifs/trending?api_key=dc6zaTOxFJmzC", UriKind.Absolute));

    this.DataContext = JsonConvert.DeserializeObject<ApiResponse>(json);

and then displaying it on the view:

        <GridView ItemsSource="{Binding data}" >
            <GridView.ItemTemplate>
                <DataTemplate>
                    <Image Source="{Binding images.original.url}"
                           MaxWidth="200" />
                </DataTemplate>
            </GridView.ItemTemplate>
            <GridView.ItemsPanel>
                <ItemsPanelTemplate>
                    <ItemsWrapGrid Orientation="Horizontal" />
                </ItemsPanelTemplate>
            </GridView.ItemsPanel>
        </GridView>


And voila, a lovely app showing lots of animated gifs:


Apps requiring the display of gifs are no longer an issue. :)



Monday, October 03, 2016

Trying out the new Windows App Development Virtual Machines #UWPLunch

All this month, I'm taking some time each day to explore (and document) things that are related to UWP development that I haven't fully investigated or used before. While doing it over lunch each day I'm calling it #UWPLunch.

At the end of last week, Microsoft (Hi Clint) announced the release of some updated virtual machine images for doing Windows App Development. While I always like having real hardware to run on (it's just faster) I appreciate the need for having a consistent development machine image and it's always good to have a backup. Recently, while preparing to move house and with all other machines packed in boxes my dev machine had a disk failure and I needed to get another dev environment set up quick to create a new release build of an app for a client who needed it ASAP. Using these VMs then might have saved me a lot of faffing around and unpacking.

Knowing these are available is great, but how easy are they to actually use?
Follow along as I see.

I started by going to the Azure portal and searching for a virtual machine that included "Windows SDK".


There's a few there so I selected the first on the list and hit create.


Then it was a case of specifying some details and selecting a machine size and specifying some network settings (which I left as all default values).

Then I just pressed OK and a VM was created for me.

Deployment took a few minutes (8 minutes and 40 seconds to be precise) and then I was able to remotely connect to it via RDP by clicking on the 'connect' link at the top of the screen.

I then entered the credential specified when creating the machine and trusted the certificate when prompted.
And then I had a virtual machine up and running and capable of use as a development environment.

All my favourite project templates are there

and I can create and run new UWP apps.


Yay!

Based on this experience I'll definitely keep a VM around and fully set up for my next UWP project. I never know when I won't have a dev machine handy but need to make a change.I'll also keep an eye out for how updates to the installed tools are handled.