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.
Wednesday, October 19, 2016
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.
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/
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.
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. :)
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:
As the title suggests, I wish this was around years ago. It would have saved me a lot of time and effort.
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.
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.
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.
Friday, October 07, 2016
Get feedback for your app via the Feedback Hub 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.
Apps that don't make it easy to provide feedback can be very frustrating for the people using them.
Windows 10 includes the Feedback Hub as a way of providing feedback and information about the OS and the apps that come with it. Additionally, you can also use it to capture feedback about your app.
I looked at this when it was first announced but it's changed since then. (Most notably the 'Feedback' class is now called 'Engagement'.) Here's how to do it now.
Firstly you need to install the Microsoft Store Services SDK.
This will let you add the appropriate reference to your project.
It's recommended that you use the standard icon to indicate the ability for you to send feedback. There's a glyph for this in the MDL2 Assets font file.
Here's how to use it in a TextBlock, but you could put it in a button too.
<TextBlock Text="" FontFamily="Segoe MDL2 Assets" />
The Feedback Hub doesn't run on as many devices as your UWP app could so you should really test fro support before trying to use it
Fortunately, there's a static method which will tell you.
Microsoft.Services.Store.Engagement.StoreServicesFeedbackLauncher.IsSupported()
To launch the feedback hub it's a simple call:
var feedback = StoreServicesFeedbackLauncher.GetDefault();
await feedback.LaunchAsync();
or if you want to send some information with ti, that's possible too.
var optionalFeedbackInfo = new Dictionary<string, string>();
optionalFeedbackInfo.Add("key", "value");
await feedback.LaunchAsync(optionalFeedbackInfo);
This will launch the app
And you'll see the feedback in the store.
Simples.
If you want more details on setting this up see the instructions at https://msdn.microsoft.com/windows/uwp/monetize/launch-feedback-hub-from-your-app
Apps that don't make it easy to provide feedback can be very frustrating for the people using them.
Windows 10 includes the Feedback Hub as a way of providing feedback and information about the OS and the apps that come with it. Additionally, you can also use it to capture feedback about your app.
I looked at this when it was first announced but it's changed since then. (Most notably the 'Feedback' class is now called 'Engagement'.) Here's how to do it now.
Firstly you need to install the Microsoft Store Services SDK.
This will let you add the appropriate reference to your project.
It's recommended that you use the standard icon to indicate the ability for you to send feedback. There's a glyph for this in the MDL2 Assets font file.
Here's how to use it in a TextBlock, but you could put it in a button too.
<TextBlock Text="" FontFamily="Segoe MDL2 Assets" />
The Feedback Hub doesn't run on as many devices as your UWP app could so you should really test fro support before trying to use it
Fortunately, there's a static method which will tell you.
Microsoft.Services.Store.Engagement.StoreServicesFeedbackLauncher.IsSupported()
To launch the feedback hub it's a simple call:
var feedback = StoreServicesFeedbackLauncher.GetDefault();
await feedback.LaunchAsync();
or if you want to send some information with ti, that's possible too.
var optionalFeedbackInfo = new Dictionary<string, string>();
optionalFeedbackInfo.Add("key", "value");
await feedback.LaunchAsync(optionalFeedbackInfo);
This will launch the app
And you'll see the feedback in the store.
Simples.
If you want more details on setting this up see the instructions at https://msdn.microsoft.com/windows/uwp/monetize/launch-feedback-hub-from-your-app
TechRewards is closing but don't ignore it yet!
Many years ago, well about 4, Nokia (remember them?) launched a program called DVLUP which offered incentives for developing and enhancing Windows Phone apps.
After the Microsoft acquisition, it was renamed as TechRewards and extended to also offer rewards for other areas (Azure) too.
But now it's time is done.
All the challenges have ended and you have until January to use any points balance to claim rewards.
Interest in the program had waned in recent months and the rewards that were available aren't as great as they used to be, but don't turn away just yet.
If you have an account that still has points don't ignore it.
You can make charitable donations from just 45pts. Don't waste your points - let others benefit from your past app development activities.
After the Microsoft acquisition, it was renamed as TechRewards and extended to also offer rewards for other areas (Azure) too.
But now it's time is done.
All the challenges have ended and you have until January to use any points balance to claim rewards.
Interest in the program had waned in recent months and the rewards that were available aren't as great as they used to be, but don't turn away just yet.
If you have an account that still has points don't ignore it.
You can make charitable donations from just 45pts. Don't waste your points - let others benefit from your past app development activities.
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:
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.
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. :)
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. :)
Book snippet from chapter 6
Hey, I'm writing a book.
Want a sample?
Great, head over to https://medium.com/@mrlacey/enabling-simpler-and-more-accurate-app-input-18fcf4f7ab3a
Want a sample?
Great, head over to https://medium.com/@mrlacey/enabling-simpler-and-more-accurate-app-input-18fcf4f7ab3a
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.
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.