Steemit is a social network that (might) pay you for using it. You can earn rewards for posting quality posts, for commenting on others posts and also for curation (voting on other people’s posts).
There is a learning process (which I am still in, even if I advanced already a little), but you can also use some bots to get some attention and make money. Better and also more sustainable than (only) using those bots, however, is to participate in the community itself by commenting and voting as well as taking part in one of several challenges on Steemit. Take a look at the extensive FAQ on Steemit to learn more.
I was following Steemit ever since I stumbled upon it, and after two days of exploring, I created my account (which took around one week back then). There were several reasons for doing that, the most important ones are
the community activity I saw and liked
my general interest in real life, average joe usable blockchain projects
being tired of Facebook, Twitter and the likes
earning some bucks (of course)
First steps on Steemit
As soon as my account was created, I started to explore Steemit more deeply. A major part of this exploration included apps I can use on my PC and my phone. After some research, I found my combo of apps/frontends for Steemit:
Being on Steemit also includes promoting it on my other existing social network accounts. And of course, I do share my posts on Facebook and Twitter, using the proper hashtags to make people (hopefully) curious.
Changes…
Yesterday, I took the time to review my last month activity on those popular and established networks. My former daily social media routine included Twitter, Facebook, and Instagram to explore new stuff and things that interest me, besides following certain RSS-Feeds (using Inoreader).
Over time, one follows a lot of accounts because of a few posts they made, but once they are no longer interesting, we do not remove them. So there is a whole lot of bullsh*t in our timelines, and it takes a lot of time to get rid of them. Also, the networks themselves do promote posts we might be interested in, which (at least for me) often miss their targets. The result is, that I avoid using these networks in my daily routine and even stop interacting with them. They are “stealing” my time, literally, if I use them.
Steemit has a few interfaces and apps that make it a bit easier for me to see the stuff I am interested in. Not so much on my developer interests, but on all other interest I have (sadly, there is very little activity of the .NET community on Steemit). So in my daily routine, Steemit took already over Twitter, Facebook, and Instagram. I do check the later ones only occasionally or when I get a notification that someone interacted with one of my accounts. This is the first time this happens within just a month.
I am posting a lot of stuff I would normally post directly to the established ones on Steemit, just to share a link to my Steemit account on those after that. I could also stop that, but I do hope that I can help to promote Steemit to the outer world by doing so.
Conclusion
Steemit is a blockchain based social network rewarding its users. The beginning of my Steemit journey was comparable with the one I had when I joined Twitter or Facebook years ago. You need to find out how everything works, build some connections, interact with others. The Steemit community (at least the parts I am interacting with) still has its spirit, which I am missing on the established networks for a long time. I will continue to focus my social activity on Steemit and to improve my interactions. I hope some of you will join and follow along.
Like I already announced in my last blog post about UWP AppServices, I am going to show you how to create a NuGet package for UWP class libraries. I am going to go through the whole process, and provide you the steps I found as easiest (it may be the case that there are other ways for the single steps, too). I am continuing with my AppServices sample to show you all the steps I did.
Preparations
The first step is to download the latest NuGet.exe. This command line application will do all the work that is needed to create the package. Once downloaded, let’s do some modifications to our project.
It is good practice to put all the NuGet stuff into a folder in your project. That’s what we’re doing now, adding a folder named NuGet and put the NuGet.exe file in it (create the folder and copy and paste it in file explorer). The next step we would do now is to open the Package Manager Console in Visual Studio and call the nuget.exe with the parameter ‘spec’ to create a .nuspec file. The.xml formatted .nuspec file describes the structure of the NuGet package.
Because we need a multi architecture package for our Universal class library, I prefer another approach. I created a sample .nuspec file that already describes part of the structure that we need. After pasting the file in, change the file name to match “[projectname].nuspec”. To add the file to your project in Visual Studio, click on the ‘ Show All Files’ button on top of the Solution Explorer Window. Now you will see the previously added NuGet folder and the .nuspec file. Right click on the renamed .nuspec file and select ‘Include in Project’:
Inside the .nuspec file
Let’s have a look into the .nuspec file. The first part is the ‘metadata’ part, which describes the file’s properties:
Just replace the the $-enclosed variables with your data. The more interesting part in this case is the dependencies part. With the Universal app platform, Microsoft introduced the .NETCore package that provides all the APIs. It is very hard to maintain the dependencies manually. Luckily, there is already a Nuget package that helps us to automate this process: NuSpec Dependency Generator.
Just add the package to your project and compile it. That’s it, you have all the dependencies in your .nuspec file:
Now that we have the dependencies in place, we’re ready for the next step: creating the package file structure. As we want a multi architecture package, we need to compile the project for every cpu architecture. This is done pretty simple, just select Release mode and build the project for all architectures:
To check if we have all files in place, just open the corresponding architectures’ folder in the bin folder of your project:
The next part is to add these folders to the .nuspec file within the ‘files’ tag:
Noticed that we use the ‘runtimes’ folder with the corresponding architecture structure folders? This is how we need to set it up for multi architectural packages. Including the .pdb files is always a good practice, even with the missing symbolication in UWP applications (at least for now. I was told from inside Microsoft that they are working on this, but it seems to be a very complicated process for .NET native compiled applications).
Very important: the entry reference
This alone does not work, though. We need a reference that we can use as entry point for our package. To do this, we need to add an additional folder entry to our .nuspec file:
[Update:] Now that we have added this folder structure to the .nuspec file, the only thing we need to do is add an AnyCPU compiled .dll. Regarding some feedback I received on Twitter, it should work if you compile the library as AnyCPU like a lot of devs are used to. I you do not have success with that like me, you can also convert the x86 .dll into an AnyCPU .dll by removing the 32Bit-flag. Here is how to do it:
Copy the x86-.dll file into the Release folder under the bin folder of your project
Copy the x86-.dll and .pri file into the Release folder
open the Visual Studio Developer Command Prompt (type ‘dev’ into the start menu, it will appear there)
type: corflags.exe /32bitreq- [path to Release folder]\[dll-Name].dll
the result should look like this:
If you have additional files like xaml files, you would need to add a new folder in the uap10.0 folder (with the same name that your project has). I’ll update this post and the sample once I have a matching sample at hand.
Creating and testing the package!
Now we are finally able to pack the NuGet package. As we have the Developer Command Prompt already open, lets change the running directory to match the NuGet folder in our project. All we then need to do is to run the pack command of the nuget.exe that we already placed in there:
And that’s it. We have our NuGet Package in place. Now let’s test our package, before we are going to upload it to nuget.org. All you need to do is to have a folder for your NuGet packages on your machine. I made a folder called ‘TestNuget’ on mine, and copied the package into it (which is the same as the Nuget push command we’ll see later).
To add this folder as package source, open the ‘Options’ menu in Visual Studio and select ‘Package Sources’ in the NuGet Package Manager entry. Hit the add symbol on top and add your folder:
Now if you open the Package Manager and select your local folder as source, you will be able to install and test your package:
Publishing the package to nuget.org (or your NuGet server)
The final step is to publish the newly generated package to nuget.org or your own NuGet server. As we still have the Developer CMD opened, we simply use the following command:
nuget push [path to your package.dll] [nuget.org API Key]
Another alternative would be to use the nuget.org website to upload the package: https://www.nuget.org/packages/upload (the page is self explanatory).
Some of you may go a different route for some steps. I have found this a good way that is also kind of memorable (for me). I would love to hear feedback on this and to discuss this, so feel free to leave me a comment.
Like always, I hope this post is helpful for some of you. Happy coding, everyone!
One of the very cool and helpful new features Microsoft added for UWP apps are AppServices. AppServices allow your application to provide functionality to other applications without even being launched. This post shows how to add and consume an AppService.
Creating the AppService
An AppService is a background task that is hosted by your application. To add an AppService to your existing application, right click on the solution name in the Solution Explorer and select ‘add new project’. Under category Windows\Universal, select ‘Windows Runtime Component’, give it a name and click on ‘OK’:
This adds a new project to your solution. Rename or Replace Class1.cs to something that matches your need (in my sample, I just use ‘Handler’). The next step is to implement the IBackgroundTask interface:
This will add the ‘Run(IBackgroundTaskInstance taskInstance)’ method to the class. Before we continue with to integrate our AppService further into the system, we need to declare two members in the Handler class:
Now that we have those two in place, let’s have a look inside the Run method:
public void Run(IBackgroundTaskInstance taskInstance)
{
//get the task instance deferral
this._backgroundTaskDeferral = taskInstance.GetDeferral();
//hooking up to the Canceled event to close app connection
taskInstance.Canceled += OnTaskCanceled;
//getting the AppServiceTriggerDetails and hooking up to the RequestReceived event
var details = (AppServiceTriggerDetails)taskInstance.TriggerDetails;
_appServiceConnection = details.AppServiceConnection;
_appServiceConnection.RequestReceived += OnRequestReceived;
}
The first step is to get a background task deferral. This allows the service to run asynchronous code against the background Task without crashing. The next step is to handle the background task’s Canceled event. Even if the Task get’s cancelled, we must complete the process and tell the OS that we have finished. If we won’t do this, the AppService will stop working on the first cancel operation. To do so, add this code to your Canceled event handling method:
this._backgroundTaskDeferral?.Complete();
Last but not least, we need to handle the request that the AppService received. To do so, we need to get the AppServiceTriggerDetails from our BackgroundTask. This allows us to get a reference to the AppServiceConnection, which provides the event ‘RequestReceived’ that we want to handle.
Within our RequestReceived event handling method, the effective work is done. As this is also an asynchronous action, we first need to get again a reference to the event’s Deferral:
This gives us a ValueSet (which works like a Dictionary), which we need to parse to get the input data we need:
var response = (string) input["question"];
The ValueSet entries you are setting up here are the parameters your consumer has to provide. In my sample, I have only a single parameter called ‘question’, but it works also well with more parameters. After we pulled the parameters out of the ValueSet, we can do the work our AppService is supposed to do.
It is a good practice to separate the function you want to provide in the AppService in a separate project. You need to write the code only once, but can use it in your main application as well as in the AppService. In my Sample, this is done in the AppServiceResponder project. It may look like an overkill in this case, but if you have more complex logic than the sample it will absolutely make sense.
I am wrapping the work into a try/finally block as we need to complete the async operation in any case to keep our AppService running. This way, even if the work is not completed successfully, at least we come out clean of the AppService Task. Within the try part of the try/finally block, we are doing the work that the service is supposed to do. The result needs to be passed as a ValueSet again. To effectively send the result to the requesting app, we use this line of code:
await args.Request.SendResponseAsync(result);
Here is the full method for reference:
private async void OnRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
{
//async operation needs a deferral
var msgDeferral = args.GetDeferral();
//picking up the data ValueSet
var input = args.Request.Message;
var result = new ValueSet();
//parsing the ValueSet
var response = (string) input["question"];
try
{
//as long as the app service connection is established we are using the same instance even if data changes.
//to avoid crashes, clear the result before getting the new one
result.Clear();
if (!string.IsNullOrEmpty(response))
{
var responderResponse = AppServiceResponder.Responder.Instance.GetResponse(response);
result.Add("Status", "OK");
result.Add("response", responderResponse);
}
await args.Request.SendResponseAsync(result);
}
//using finally because we need to tell the OS we have finished, no matter of the result
finally
{
msgDeferral?.Complete();
}
}
Declaring the App Service in the host app
The final step we need to apply is to declare the AppService in our Package.appxmanifest. Declaring the AppService is pretty simple. Just select ‘App Service’ in the dropdown and hit ‘Add’. Give it a name (Microsoft recommends ‘reverse domain name style ‘, so I used it. The last step is to declare the Entry point, which is AppServiceNamespace.ClassName (replace with yours).
The result should look like this:
Now build the solution. If all is set up correct, you have made an application implementing an AppService.
Creating the AppService Connector
Like I recommend to extract functionality that runs inside the AppService, I do so for the code that connects the app into a separate project. This allows you to reuse the project in multiple apps. An additional advantage is that you can create a Nuget package for this separate project to provide this functionality to other developers (I will write a separate post about this to keep this one focused on the AppService).
After adding a new project to the Solution, rename/replace also here Class1. I named my handler class just Connector. To make it a no brainer to use the connector, I implemented the class as singleton:
private static Connector _instance;
public static Connector Instance => _instance ?? (_instance = new Connector());
After that, I added an asynchronous Task that returns the AppService’s response. Let’s have a look inside the task. Inside the using statement for the AppServiceconnection, the first thing we need to do is to call the AppService with these three lines of code:
//declaring the service and the package family name
SampleAppServiceConnection.AppServiceName = "com.msiccdev.sampleappservice";
//this one can be found in the Package.appxmanifest file
SampleAppServiceConnection.PackageFamilyName = "acc75b1a-8b90-4f18-a2c4-08b0d700f1c6_62er76fr5b6k0";
//trying to connect to he AppService
AppServiceConnectionStatus status = await SampleAppServiceConnection.OpenAsync();
We’ll get a AppServiceConnectionStatus back, which helps us to deside how to go on in the task. If we do not have success in getting a connection to the AppService, I am returning an error description. For this, I created a simple helper method:
private string GetStatusDetail(AppServiceConnectionStatus status)
{
var result = "";
switch (status)
{
case AppServiceConnectionStatus.Success:
result = "connected";
break;
case AppServiceConnectionStatus.AppNotInstalled:
result = "AppServiceSample seems to be not installed";
break;
case AppServiceConnectionStatus.AppUnavailable:
result =
"App is currently not available (could be running an update or the drive it was installed to is not available)";
break;
case AppServiceConnectionStatus.AppServiceUnavailable:
result = "App is installed, but the Service does not respond";
break;
case AppServiceConnectionStatus.Unknown:
result = "Unknown error with the AppService";
break;
}
return result;
}
For the case we are successful with our connection attempt , I am sending the needed ValueSet with these lines:
var input = new ValueSet() {{"question", question}};
AppServiceResponse response = await SampleAppServiceConnection.SendMessageAsync(input);
I am using a simple ValueSet with just one value here, but I have already done it with a more complex structure and this works as well. I haven’t reached any limits by now, but I think that they are the same as for all Background Tasks (don’t throw stones at me if it is different). The only thing I then need to do is to handle the response according to its status with this switch statement:
switch (response.Status)
{
case AppServiceResponseStatus.Success:
result = (string) response.Message["response"];
break;
case AppServiceResponseStatus.Failure:
result = "app service called failed, most likely due to wrong parameters sent to it";
break;
case AppServiceResponseStatus.ResourceLimitsExceeded:
result = "app service exceeded the resources allocated to it and had to be terminated";
break;
case AppServiceResponseStatus.Unknown:
result = "unknown error while sending the request";
break;
}
As we already know by know, we receive a ValueSet as response message. In my sample, I am returning only the response string. That’s it, we are already able to run use the AppService via the Connector. For demo purposes, I added also a simple AppService consumer app. Once the user puts in a question and hits the answer button, the result from the AppService gets displayed. All we need is just one line of code:
Pretty easy to use, right? Here is a screen shot from the consumer app:
That’s all we need for our AppService. Bonus of the project structure I used: You can provide a Nuget Package for other devs to consume your AppService. How? I will write about this in my next blog post.
Even if this is not a MVVM structured app, it absolutely works in there, too. If you want to have a look on a live in the Store app that uses MVVM and an AppService, click here. For using the AppService within your app, just download this Nuget Package into your app. Otherwise, I created a complete working sample and pushed it on my Github account right here. Feel free to play around with it to explore AppServices a bit more. As always, I hope this post is helpful for some of you.
This is a blog post not only for developers, but also for users (I will try to get not to technical in this post). I managed to buy a Microsoft Band 2 for me here in Europe two weeks ago, and of course I am still exploring all the functionality that it has. A web tile is one of the cool features it supports – with a web tile, you can add your digital footprint to the Microsoft Band. And the best thing: you don’t need to be a developer to create your own! Microsoft provides a web kit that creates the tile for you!
Let’s have a look at the (not so hard to understand) steps it takes to create your own web tile:
The First step is to choose the layout, which also describes the type of the web tile:
After selecting the feed tile template, you need to find the RSS url of your blog or other source site. Paste it in the desired field and hit the next button.
Microsoft’s site now reads your RSS feed and provides you the single fields that come with your feed. When you hover with your mouse over the fields, they’’ll get highlighted. Just drag and drop them into the Microsoft Band preview image on the left hand side.
Now that you have selected the data that should appear on the Microsoft Band, let’s set up the notification for the web tile. This is where it gets a bit tricky, but most feeds should be covered by the following image:
No worries, I am telling you what is done here. The first and second line is the title and the description of the notification. You can put in there whatever you like. The most important part is the condition expression below the Band preview. Sadly the documentation provided by Microsoft is not as detailed for feed tiles as it should. Luckily, I found a post at StackOverflow that explains a little bit more. If you’re a developer, feel free to read the full text. If you are a user: just drag and drop the guid field of the “item” section into the first and also into the last field and set the condition to not equal. If your feed gets a new item, you will get a notification on your band with that. This condition looks if there is any new guid in the items list of your feed – and if so, sends out the notification and shows the badge.
In the last step, we just need to provide some details about the web tile we have created. If you want to have all features, you must provide both images:
If you want to have control on how the image looks like, you should provide the images already flattened into a transparent and white image already. The result could look very creepy otherwise. After that, you have finally created your web tile – congratulations!
Once you have downloaded the web tile, you just need to mail it to yourself or anyone who wants to use it. The other option is to put it on your OneDrive and just share a link to your web tile. To share the link you need to add the link of your online storage to this: “mshealth-webtile://?action=download-manifest&url=”. The web tile I created for my blog is in this case: mshealth-webtile://?action=download-manifest&url=http://1drv.ms/1TDRGSC . This link only works on phones (also Android and iOS). It opens the Microsoft Health app (that needs to be installed for the usage of web tiles, anyways) and asks you to install the web tile:
Once you have done that, your web tile is ready to go. Once you have a new entry in your RSS feed, the notification should appear on your band. If you want to force the update, just force the Microsoft Health app to sync with your band. After that, you should see the notification and also the badge count. Here is a shot of the one I did for testing:
I only began to play around with web tiles, and already was able to create a pretty good result so far. As I will explore them more and more, I will continue to blog about it. In the meantime, I hope this blog post is helpful for some of you. Have fun, everybody!
If your app performs actions, you most probably want to add also some confirmation if an action has finished. There are some ways to do this, like using local toast notifications or MessageDialogs. While I was working on Voices Admin v2, which is a universal app, I came along with a helper to simplify using local toast notifications. However, there came the point, where I got annoyed by the sound of these, and I looked into possible ways to replace them. My solution is a simple notification system, that uses the MVVM Light Messenger.
The first thing I did was adding a new property that broadcasts its PropertyChangedMessage to my ExtendedViewModelBase (which inherits from the MVVM Light ViewModelBase). This simplifies setting the notification text across multiple ViewModels as I don’t need to create a property in every ViewModel of my app:
public class ExtendedViewModelBase : ViewModelBase
{
public ExtendedViewModelBase()
{
}
/// <summary>
/// The <see cref="NotificationText" /> property's name.
/// </summary>
public const string NotificationTextPropertyName = "NotificationText";
private string _notificationText = string.Empty;
/// <summary>
/// Sets and gets the NotificationText property.
/// Changes to that property's value raise the PropertyChanged event.
/// This property's value is broadcasted by the MessengerInstance when it changes.
/// </summary>
public string NotificationText
{
get
{
return _notificationText = string.Empty;
}
set
{
Set(() => NotificationText, ref _notificationText, value, true);
}
}
}
The second step is to create the possibility to bind this into my view. I am using a custom PageBase class to simplify this. For those binding purposes it is common to add a DependencyProperty, and this is exactly what I did:
/// <summary>
/// global property to bind the notification text against
/// </summary>
public static readonly DependencyProperty AppNotificationTextProperty = DependencyProperty.Register(
"AppNotificationText", typeof (string), typeof (PageBase), new PropertyMetadata(string.Empty, (s, e) =>
{
var current = s as PageBase;
if (current == null)
{
return;
}
current.CheckifNotificationMessageIsNeeded(s);
}));
/// <summary>
/// gets or sets the AppNotificationText
/// </summary>
public string AppNotificationText
{
get { return (string)GetValue(AppNotificationTextProperty); }
set { SetValue(AppNotificationTextProperty, value); }}
You may have noticed that I hooked up into the PropertyChangedCallback of the DependecyProperty, which passes the execution to an separate method. Before we’ll have a look on that method, we need to add two private members to my PageBase: one for a StackPanel (mainly to set the Background color) and another one for Textblock. This is needed because this is the visible part of the notification. In the constructor of my PageBase class, I am filling them with live and connect them together:
//instantiate and create StackPanel and TextBlock
//you can put anything you want in the panel
_panel = new StackPanel()
{
Background = new SolidColorBrush(Colors.Blue),
Visibility = Visibility.Collapsed,
};
_textBlock = new TextBlock()
{
FontSize = 20,
Margin = new Thickness(39, 10, 10, 10),
TextAlignment = TextAlignment.Center
};
_panel.Children.Add(_textBlock);
The next thing we need to do is the FindChildren<T> helper method, which I took from the MSDN docs:
/// <summary>
/// Gets a list of DependencyObjects from the Visual Tree
/// </summary>
/// <typeparam name="T">the type of the desired object</typeparam>
/// <param name="results">List of children</param>
/// <param name="startNode">the DependencyObject to start the search with</param>
public static void FindChildren<T>(List<T> results, DependencyObject startNode) where T : DependencyObject
{
int count = VisualTreeHelper.GetChildrenCount(startNode);
for (int i = 0; i < count; i++)
{
var current = VisualTreeHelper.GetChild(startNode, i);
if ((current.GetType()) == typeof(T) || (current.GetType().GetTypeInfo().IsSubclassOf(typeof(T))))
{
T asType = (T)current;
results.Add(asType);
}
FindChildren<T>(results, current);
}
}
This helper enables us to find the top level grid, where we will add the StackPanel and control its visibilty and the TextBlock’s text. Which we are doing with the CheckifNotificationMessageIsNeeded() method:
/// <summary>
/// handles the visibility of the notification
/// </summary>
/// <param name="currentDependencyObject">the primary depenedency object to start with</param>
private void CheckifNotificationMessageIsNeeded(DependencyObject currentDependencyObject)
{
if (currentDependencyObject == null) return;
var children = new List<DependencyObject>();
FindChildren(children, currentDependencyObject);
if (children.Count == 0) return;
var rootGrid = (Grid)children.FirstOrDefault(i => i.GetType() == typeof(Grid));
if (rootGrid != null)
if (!string.IsNullOrEmpty(AppNotificationText))
{
if (!rootGrid.Children.Contains(_panel))
{
rootGrid.RowDefinitions.Add(new RowDefinition() {Height = new GridLength(_panel.ActualHeight, GridUnitType.Auto)});
_panel.SetValue(Grid.RowProperty, rootGrid.RowDefinitions.Count);
rootGrid.Children.Add(_panel);
}
_textBlock.Text = AppNotificationText;
_panel.Visibility = Visibility.Visible;
}
else if (string.IsNullOrEmpty(AppNotificationText))
{
_textBlock.Text = string.Empty;
_panel.Visibility = Visibility.Collapsed;
}
}
Once we have the rootGrid on our Page, we are adding a new Row, set the StackPanel’s Grid.Row property to that and finally add the StackPanel to the Grid’s Children – but only if it does not exist already. No everytime the AppNotificationText property changes, the visibility of the StackPanel changes accordingly. Same counts for the TextBlock’s text. That’s all we need to do in the PageBase class.
The final bits of code we have to add are in the MainViewModel. I am using the MainViewModel as a kind of root ViewModel, which controls values and actions that are needed across multiple ViewModels. If you do not use it in the same way, you might need to write that code in all of your ViewModels where you want to use the notifications. The biggest advantage of my way is that the notification system (and other things) also works across pages.
The first thing we need is of course a property for the notification Text, which we will use to bind against on all pages where we want to use the notification system:
/// <summary>
/// The <see cref="GlobalNotificationText" /> property's name.
/// </summary>
public const string GlobalNotificationTextPropertyName = "GlobalNotificationText";
private string _globalNotificationText = string.Empty;
/// <summary>
/// Sets and gets the GlobalNotificationText property.
/// Changes to that property's value raise the PropertyChanged event.
/// </summary>
public string GlobalNotificationText
{
get
{
return _globalNotificationText;
}
set
{
Set(() => GlobalNotificationText, ref _globalNotificationText, value);
}
}
Now we have this, we are hooking into the MVVM Messenger to catch the broadcasted NotificationText’s PropertyChangedMessage:
If we would stop here, you would need to find a good point to set the NotificationText (and/or the GlobalNotificationText) property back to an empty string. This can be like the search a needle in the hay, believe me. That’s why I am giving every notification 5 seconds to be displayed, and the I am resetting the GlobalNotificationText property in my MainViewModel automatically. To achieve this goal, I am using a simple DispatcherTimer with an Interval of 1 second:
_notificationTimer = new DispatcherTimer() { Interval = new TimeSpan(0, 0, 1) };
DispatcherTimer has a Tick event, which fires every time a Tick happened. In our case, it fires every second. Hooking up into this event is essential, so add this line of code and let Visual Studio create the handler for you:
Inside the Tick event handler, I am counting the ticks (using a private member in my MainViewModel). Once the timer passed 5 seconds, I am stopping the DispatcherTimer, reset the counter and finally set the GlobalNotificationText property back to empty, which causes the notification to disappear:
Of course we also need to start the DispatcherTimer. The perfect time for this is within the handler of the received PropertyChangedMessage we added earlier:
//register for the global NotificationText PropertyChangedMessage from all VMs that derive from ExtendenViewModelBase
Messenger.Default.Register<PropertyChangedMessage<string>>(this, message =>
{
if (message.PropertyName == ExtendedViewModelBase.NotificationTextPropertyName)
{
if (!_notificationTimer.IsEnabled)
{
_notificationTimer.Start();
}
else
{
_notificationTimerElapsedSeconds = 0;
}
GlobalNotificationText = message.NewValue;
}
});
I am just checking if the DispatcherTimer is not yet enabled (= running) and start the timer in this case. If it is already running, I am just resetting my counter property to make sure that the notification is visible for 5 seconds again.
That’s it. Your MVVM (Light) app has now a simple and not so annoying notification system. It also provides the same experience across both platforms. There are sure ways to improve this here and there, that’s why I put up a sample to play around and contribute to on my Github account.
As always, I hope this post is helpful for some of you.
Late in 2014, Microsoft finally started Application Insights (AI), their own telemetry service for all kind of apps. For Windows (Phone) 8.1 apps, the service was a long running beta. This month, Microsoft finally released version 1.0 of Application Insights for Windows apps.
However, if you are upgrading from a previous version, you will see that AI will no longer send any data to Azure. This has a very simple reason. Microsoft moved the configuration from the former ApplicationInsights.config file to a class called WindowsAppInitializer. I only found this out because I commented at the corresponding documentation site, which causes Microsoft to send me an email with a link to the solution in the forums. You will not find these info in the documentation as of writing this blog post. Microsoft also updated the docs tonight.
I strongly recommend you to remove all old references in favor of just updating to avoid any glitches with the new API.
I played around with the new WindowsAppInitializer class. If you want to collect all data with the automatic WindowsCollectors, all you have to add to your code is one line in your App.xaml.cs constructor (Microsoft recommends to add it before all other code):
That’s it. Really. Here’s a screen shot of the test app in Visual Studio I created to play around with the new WindowsAppInitializer class:
As you can see, telemetry data gets written to the debug output, and with that, it will be submitted to your Azure account. If you do not want to use all Collectors, just add those you want to use after your InstrumentationKey, separated with ‘|’ in the IninitalizeAsync Method.
Adding custom telemetry data collection is still possible. Quick sample:
var tc = new TelemetryClient();
tc.TrackEvent("MainPage loaded... [WP TestEvent]");
This will send this string as a custom event to your Azure account. For more info about custom telemetry data, check this page.
As always, I hope this blog post is helpful for some of you.
[Updated: This post caused a lot of controversy and bad voices, but luckily also some constructive feedback. This is not the initial, but the updated version of this post.]
One of the goals of a Universal Windows app project is to simplify the life of our users. Microsoft provides access to RoamingSettings as well as the RoamingFolder to achieve this goal.
The usage of this storage is fairly simple (it is the same as using the local counterparts). However, one big point is how to save those settings and files securely. Nowadays, a lot of users are even more concerned about security than before, and it makes all sense to encrypt synchronized data.
This is how I came a long with a helper class string encryption. I have searched a lot throughout the Web, but apparently this is not a topic to be discussed openly but behind closed doors. I partly understand that, but I want to say thanks to Ginny Caughey at this point for her feedback on security, and also thank Joost van Schaik for his feedback that “forced” me to change my helper class to extension methods, which makes the usage more readable. If you want to learn more about Extension Methods, this link helped me to understand them and made me changing my code in about 5 minutes.
Let’s talk about security. There are two patterns for encrypting sensitive data: using symmetric algorithm and using asymmetric algorithm. The symmetric key encryption is secure, as long as you have a truly unique identifier that you can use as encryption key. Being very fast, using the symmetric algorithm is only as secure as the key that is used for encryption (obviously, I did it wrong in the first place, that’s why the code is updated). More security is achieved with the asymmetric algorithm, where a public and a private key are used for encryption. The downside of this higher level of security is that it takes longer to perform those actions. There are also more differences between those methods, but that would fill a whole book.
I have learned that on Android and iOS, often the AdvertisingId is used for such operations. Also Windows 8.1 (both phone and PC/tablet) have such an Id, provided by the AdvertisingManager class. Be aware that the id is per-user and per-device and users can switch this off or even reset their advertising id, so this is not a good idea to use. In Windows 8.1 Runtime projects (both phone and tablet/PC, we luckily have the PasswordVault class. This brings us some key advantages: the PasswordVault is encrypted and it does roam to trusted devices. This is what I am using for saving the keys, being it the symmetric one or the asymmetric ones.
Before we will have a look at my Extension methods, I have to put in a disclaimer. I am not saying that my way is the nonplus ultra way to encrypt strings. I do also not say that my way provides 100% security (which in fact does not even exist). My way provides security at a good level, but that level surely can be improved. I will take no responsibility for the security of apps that are using this.
Let’s have a look at my Extension methods that will help you securing your data.
Symmetric Key Encryption
My symmetric encryption methods were using a pre shared key. I received a lot of feedback that this does not make any sense as it throws away the security factor, especially as the Guid can be recalculated. So I changed the method to use random data, that is generated from the CryptographiBuffer.GenerateRandom() method. Then I am putting this into an Base64 encoded string to pass it over to the PasswordVault:
public static string GetKeyMaterialString(string resource = null, string username = null)
{
string key = "";
if (string.IsNullOrEmpty(resource) && string.IsNullOrEmpty(username))
{
//replace with your resource name if suitable
resource = "symmetricKey";
//replace with your user's name/identifier
username = "sampleUserName";
}
//using try catch as FindAllByResource will throw an exception anyways if the specified resource is not found
try
{
//search for our saved symmetric key
var findSymmetricKey = _passwordVault.FindAllByResource(resource);
//calling RetrievePassword you MUST!
findSymmetricKey[0].RetrievePassword();
key = findSymmetricKey[0].Password;
}
catch (Exception)
{
//getting a true random key buffer with a length of 32 bytes
IBuffer randomKeyBuffer = CryptographicBuffer.GenerateRandom(32);
key = CryptographicBuffer.EncodeToBase64String(randomKeyBuffer);
_passwordVault.Add(new PasswordCredential(resource, username, key));
}
return key;
}
The resource string as well as the username is needed to save the key into the PasswordVault. The FindAllByResource() method will throw an Exception if no credentials are found, in this case we are generating them from scratch in the catch block.
The encryption method is pretty straight forward as well. Microsoft does all the complicated calculating stuff, we just need to call the proper methods. What you get is a Base64 encoded string that easily can be saved into the ApplicationSettings or wherever you need it. Here is the complete extension method:
public static string EncryptStringSymmetric(this string text)
{
string encryptedString = "";
try
{
//load the alghorithm providers
var symmetricKeyProvider = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.AesCbcPkcs7);
//create the symmetric key that is used to encrypt the string from random keystring
var cryptoKey = symmetricKeyProvider.CreateSymmetricKey(CryptographicBuffer.DecodeFromBase64String(GetKeyMaterialString()));
//create the IBuffer that is for the string
IBuffer buffer = CryptographicBuffer.CreateFromByteArray(Encoding.UTF8.GetBytes(text));
//encrypt the byte array with the symmetric key
encryptedString = CryptographicBuffer.EncodeToBase64String(CryptographicEngine.Encrypt(cryptoKey, buffer, null));
//return the Base64 string representation of the encrypted string byte array
return encryptedString;
}
catch (Exception)
{
return null;
}
}
The decryption method of course reverses all this. First, it loads the saved key from the password fault, and then decrypts and returns then the plain text string:
public static string DecryptStringSymmetric(this string text)
{
string decryptedString = "";
try
{
//load the alghorithm providers
var symmetricKeyProvider = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.AesCbcPkcs7);
//create the symmetric key that is used to encrypt the string from random keystring
var cryptoKey = symmetricKeyProvider.CreateSymmetricKey(CryptographicBuffer.DecodeFromBase64String(GetKeyMaterialString()));
//decode the input Base64 string
IBuffer buffer = CryptographicBuffer.DecodeFromBase64String(text);
//declare new byte array
byte[] dectryptedBytes;
//decrypt the IBuffer back to byte array
CryptographicBuffer.CopyToByteArray(CryptographicEngine.Decrypt(cryptoKey, buffer, null), out dectryptedBytes);
//get string back from the byte array
decryptedString = Encoding.UTF8.GetString(dectryptedBytes, 0, dectryptedBytes.Length);
//return plain text
return decryptedString;
}
catch (Exception)
{
return null;
}
}
Both methods return null if anything did not work like excepted. This should help you to easily check if something went wrong in there. Here is how to use those methods:
Encrypting the string:
var encryptedString = stringToEncrypt.EncryptStringSymmetric();
Decrypting the string:
var dectryptedString = stringToDecrypt.DecryptStringSymmetric();
Asymmetric Key Encryption
Like I already wrote, for asymmetric encryption always two keys are used. The method to get the keys is there slightly different:
public static Dictionary<string, string> GetAsymmetricKeyPair(string username = null)
{
Dictionary<string, string> keyDictionary;
const string privKey = "asymmetricPrivateKey";
const string pubKey = "asymmetricPublicKey";
if (string.IsNullOrEmpty(username))
{
//replace with your user's name/identifier
username = "sampleUserName";
}
//using try catch as FindAllByResource will throw an exception anyways if the specified resource is not found
try
{
//search for our save asymmetric keys
var findAsymmetricPrivateKey = _passwordVault.FindAllByResource(privKey);
//calling RetrievePassword you MUST!
findAsymmetricPrivateKey[0].RetrievePassword();
var findAsymmetricPublicKey = _passwordVault.FindAllByResource(pubKey);
//calling RetrievePassword you MUST!
findAsymmetricPublicKey[0].RetrievePassword();
//loading our keys into a new Dictionary
keyDictionary = new Dictionary<string, string>()
{
{privKey, findAsymmetricPrivateKey[0].Password},
{pubKey, findAsymmetricPublicKey[0].Password}
};
}
catch (Exception)
{
//declaring the Key Algortihm Provider and creating the KeyPair
var asymmetricKeyProvider =
AsymmetricKeyAlgorithmProvider.OpenAlgorithm(AsymmetricAlgorithmNames.RsaPkcs1);
CryptographicKey cryptographicKeyPair = asymmetricKeyProvider.CreateKeyPair(512);
//converting the KeyPair into IBuffers
IBuffer privateKeyBuffer =
cryptographicKeyPair.Export(CryptographicPrivateKeyBlobType.Pkcs1RsaPrivateKey);
IBuffer publicKeyBuffer =
cryptographicKeyPair.ExportPublicKey(CryptographicPublicKeyBlobType.Pkcs1RsaPublicKey);
//encoding the key IBuffers into Base64 Strings and adding them to a new Dictionary
keyDictionary = new Dictionary<string, string>
{
{privKey, CryptographicBuffer.EncodeToBase64String(privateKeyBuffer)},
{pubKey, CryptographicBuffer.EncodeToBase64String(publicKeyBuffer)}
};
//saving the newly generated keys in PasswordVault
//it is recommended to save the both keys separated from each other, though
_passwordVault.Add(new PasswordCredential(privKey, username, keyDictionary[privKey]));
//_passwordVault.Add(new PasswordCredential(pubKey, username, keyDictionary[pubKey]));
}
//return new Dictionary
return keyDictionary;
}
As you can see, I am creating a Dictionary that holds the two keys so we can work with. I also use another key generating method, specially made for asymmetric encryption. I store those two keys separated from each other into the PasswordVault in the end.
The encryption follows basically the same structure as the symmetric key encryption method. Due to the fact I already have two different keys, I think this is ok for the scenario of passing values between the Windows Phone and Windows project. Eventually I will change that in future when I see the need for it. Notice that for encryption, always the public key is used. The public key should also be saved separated from the private key. So here is the complete method:
public static string EncryptStringAsymmetric(this string text, string publicKey = null)
{
//making sure we are providing a public key
if (string.IsNullOrEmpty(publicKey))
{
var keyPairs = GetAsymmetricKeyPair();
publicKey = keyPairs["asymmetricPublicKey"];
}
try
{
//converting the public key into an IBuffer
IBuffer keyBuffer = CryptographicBuffer.DecodeFromBase64String(publicKey);
//load the public key and the algorithm provider
var asymmetricAlgorithmProvider = AsymmetricKeyAlgorithmProvider.OpenAlgorithm(AsymmetricAlgorithmNames.RsaPkcs1);
var cryptoKey = asymmetricAlgorithmProvider.ImportPublicKey(keyBuffer, CryptographicPublicKeyBlobType.Pkcs1RsaPublicKey);
//converting the string into an IBuffer
IBuffer buffer = CryptographicBuffer.CreateFromByteArray(Encoding.UTF8.GetBytes(text));
string encryptedString = "";
//perform the encryption
encryptedString = CryptographicBuffer.EncodeToBase64String(CryptographicEngine.Encrypt(cryptoKey, buffer, null));
//return the Base64 string representation of the encrypted string
return encryptedString;
}
catch (Exception)
{
return null;
}
}
The decryption of the encrypted string works also in a similar way to the symmetric one, except we are using the private key of our asymmetric key pair. To be able to do this, we need to use the ImportKeyPair method, whose name is a bit misleading in my opinion. In fact, we even need to specify that we want to import the private key and not the whole key pair. But even with that, decryption works like expected:
public static string DecryptStringAsymmetric(this string text, string privateKey = null)
{
//making sure we are providing a public key
if (string.IsNullOrEmpty(privateKey))
{
var keyPairs = GetAsymmetricKeyPair();
privateKey = keyPairs["asymmetricPrivateKey"];
}
try
{
//converting the private key into an IBuffer
IBuffer keyBuffer = CryptographicBuffer.DecodeFromBase64String(privateKey);
//load the private key and the algorithm provider
var asymmetricAlgorithmProvider = AsymmetricKeyAlgorithmProvider.OpenAlgorithm(AsymmetricAlgorithmNames.RsaPkcs1);
var cryptoKey = asymmetricAlgorithmProvider.ImportKeyPair(keyBuffer, CryptographicPrivateKeyBlobType.Pkcs1RsaPrivateKey);
//converting the encrypted text into an IBuffer
IBuffer buffer = CryptographicBuffer.DecodeFromBase64String(text);
//cdecrypting the IBuffer and convert its content into a Byte array
byte[] decryptedBytes;
CryptographicBuffer.CopyToByteArray(CryptographicEngine.Decrypt(cryptoKey, buffer, null), out decryptedBytes);
string decryptedString = "";
//getting back the plain text
decryptedString = Encoding.UTF8.GetString(decryptedBytes, 0, decryptedBytes.Length);
return decryptedString;
}
catch (Exception)
{
return null;
}
}
Like the symmetric methods, also the asymmetric methods return null if something went wrong. Here is how to use them:
Encrypting the string:
var encryptedString = stringToEncyrpt.EncryptStringAsymmetric();
Decrypting the string:
var decryptedString = stringToDecrypt.DecryptStringAsymmetric();
As you can see, securing strings does not have to be more complicated than this. Using the PasswordVault, we have a truly secure place to store the keys (that need to be saved privately and secure), the rest is done by the methods provided by the operating system. I am by far not a security researcher or expert, but this class should provide a good level of security for string encryption in Windows 8.1 universal apps.
If you know more about security or have ideas to improve this helper class, I put up a sample project on Github where you also can play around with the class and the simple app I created for it. Feel free to contribute to this class or discuss in the comments below.
Now that I am on a good way to understand and use the MVVM pattern, I am also finding that there are some times rather simple solutions for every day problems. One of these problems is that we don’t have a global progress indicator for Windows Universal apps. That is a little bit annoying, and so I wrote my own solution. I don’t know if this is good or bad practice, but my solution is making it globally available in a Windows Universal app. The best thing is, you just need to bind to a Boolean property to use it. No Behaviors, just the one base implementation and Binding (Yes, I am a bit excited about it). For your convenience, I attached a demo project at the end of this post.
To get the main work for this done, we are implementing our own class, inherited from the Page class. The latter one is available for Windows as well as Windows Phone, so we can define it in the shared project of our Universal app. To do so, add a new class in the shared project. I named it PageBase (as it is quite common for this scenario, as I found out).
First, we need to inherit our class from the Page class:
public abstract class PageBase : Page
Now that we have done this, we need a global available property that we can bind to. We are using a DependencyProperty to achieve this goal. To make the property reflect our changes also to the UI, we also need to hook into a PropertyChanged callback on it:
//this DepenedencyProperty is our Binding target to get all the action done!
public static readonly DependencyProperty IsProgressIndicatorNeededProperty = DependencyProperty.Register(
"IsProgressIndicatorNeeded", typeof (bool), typeof (PageBase), new PropertyMetadata((bool)false, OnIsProgressIndicatorNeededChanged));
public static void OnIsProgressIndicatorNeededChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
}
//get and send the value of our Binding target
public bool IsProgressIndicatorNeeded
{
get { return (bool) GetValue(IsProgressIndicatorNeededProperty); }
set { SetValue(IsProgressIndicatorNeededProperty, value); }
}
The next step we need to do is to find the UIElement we want the progress indicator to be in. To do so, we are going through the VisualTree and pick our desired element. This helper method (taken from the MSDN documentation) will enable us to find this element:
//helper method to find children in the visual tree (taken from MSDN documentation)
private static void FindChildren<T>(List<T> results, DependencyObject startNode)
where T : DependencyObject
{
int count = VisualTreeHelper.GetChildrenCount(startNode);
for (int i = 0; i < count; i++)
{
var current = VisualTreeHelper.GetChild(startNode, i);
if ((current.GetType()) == typeof(T) || (current.GetType().GetTypeInfo().IsSubclassOf(typeof(T))))
{
T asType = (T)current;
results.Add(asType);
}
FindChildren<T>(results, current);
}
}
The method goes through the VisualTree, starting at the point we are throwing in as DependecyObject and gives us a List<T> with all specified Elements. From this List we are going to pick our UIElement that will hold the progress indicator for us. Let’s create a new method that will do all the work for us:
Notice the DependencyObject parameter? This makes it easier for us to use the method in different places (which we will, more on that later). Let’s get our list of DependencyObjects from our parameter and pick the first Grid as our desired UIElement to hold the progress indicator:
if (currentObject == null) return;
//getting a list of all DependencyObjects in the visual tree
var children = new List<DependencyObject>();
FindChildren(children, currentObject);
if (children.Count == 0) return;
//getting a reference to the first Grid in the visual tree
//this can be any other UIElement you define
var rootGrid = (Grid)children.FirstOrDefault(i => i.GetType() == typeof(Grid));
Now that we have this, we are already at the point where we need to create our progress indicator object. I declared a class member of type ProgressBar (which needs to be instantiated in the constructor then). This is how I set it up:
//setting up the ProgressIndicator
//you can also create a more complex object for this, like a StackPanel with a TextBlock and the ProgressIndicator in it
_progressIndicator.IsIndeterminate = IsProgressIndicatorNeeded;
_progressIndicator.Height = 20;
_progressIndicator.VerticalAlignment = VerticalAlignment.Top;
The final step in the PageBase class is to check if there is already a chikd of type ProgressBar, if not adding it to the Grid and setting it’s Visibility property to Visible if our above attached DependencyProperty has the value ‘true’:
//showing the ProgressIndicator
if (IsProgressIndicatorNeeded)
{
//only add the ProgressIndicator if there isn't already one in the rootGrid
if (!rootGrid.Children.Contains(_progressIndicator))
{
rootGrid.Children.Add(_progressIndicator);
}
_progressIndicator.Visibility = Visibility.Visible;
}
If the value is ‘false’, we are setting the Visibility back to collapsed:
//hiding the ProgressIndicator
else
{
if (rootGrid.Children.Contains(_progressIndicator))
{
_progressIndicator.Visibility = Visibility.Collapsed;
}
}
Now that we have this method in place, let’s go back to our callback method we have been hooking into earlier. To reflect the changes that we are throwing into our DependencyProperty, we are calling our method within the PropertyChanged callback. To do so, we are getting a reference to the PageBase class, which is needed because we are in a static method. Once we have this reference, we are calling our method to show/hide the progress indicator:
public static void OnIsProgressIndicatorNeededChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
//resolving d as PageBase to enable us calling our helper method
var currentObject = d as PageBase;
//avoid NullReferenceException
if (currentObject == null)
{
return;
}
//call our helper method
currentObject.CheckIfProgressIndicatorIsNeeded(d);
}
That’s all, we are already able to use the global progress indicator. To use this class, you need to do a few things. First, go to the code-behind part of your page. Make the class inherit from the PageBase class:
public sealed partial class MainPage : PageBase
Now, let’s go to the XAML part and add a reference to your class:
If you now add two buttons to the mix, binding their Commands to change the value of the Boolean property, you will see that you can switch the loading dots on and off like you wish. That makes it pretty easy to use it in a MVVM driven application.
But what if we need to show the progress indicator as soon as we are coming to the page? No worries, we are already prepared and need only a little more code for that. In the PageBase class constructor, register for the Loaded event:
Loaded += PageBase_Loaded;
In the Loaded event, we are calling again our main method to show the progress indicator, but this time we use the current window content as reference to start with:
void PageBase_Loaded(object sender, RoutedEventArgs e)
{
//using the DispatcherHelper of MvvmLight to get it running on the UI
DispatcherHelper.CheckBeginInvokeOnUI(() =>
{
//Window.Current.Content is our visual root and contains all UIElements of a page
var visualRoot = Window.Current.Content as DependencyObject;
CheckIfProgressIndicatorIsNeeded(visualRoot);
});
}
As we need to reflect changes on the UI thread, I am using the DispatcherHelper of the MvvmLight Toolkit. You can use your own preferred method as well for that. That’s all, If you now test it with setting the IsProgressIndicatorNeeded property in your page directly to ‘True’ in XAML, you will see the loading dots right from the start.
Like always, I hope this is helpful for some of you.
Often , we need to display a confirmation that some action in our app has been finished (like some data has been updated etc.). There are several ways of doing this, like displaying a MessageBox or MessageDialog. This however breaks the user interaction, and a lot of users will start complaining on that if your app keeps doing so. There needs to be a better way.
With the Coding4fun Toolkit floating around, you can mimic a toast notification – sadly only on Windows Phone (at least for the moment, but Dave told me he will work on implementing it for Windows, too). Also, Toastinet library is floating around, which is also able to mimic the toast notification behavior (although for Windows Universal app, the implementation is not that intuitive as for Windows Phone). Both are fantastic libraries that I used in the past, but I wanted a solution that is implemented easily and works with my Universal app. So I did some searching in the Web and the MSDN docs, and found out that is pretty easy to use the system toast notifications on both platforms locally.
There are 8 possible ways to format toast notifications (as you can see here in the toast template catalog). This gives us pretty much options on how a notification can be styled. However, most options just work on Windows 8.1, while Windows Phone 8.1 apps will only show the notification in the way “app logo” “bold text” “normal text”. However, the notification system takes care of that, so you can specify some other type on Windows 8.1, while knowing that it gets converted on Windows Phone automatically. This allows us to write a helper class that implements all possible options without any headache.
the code parts for the notification
Let’s have a look at the code parts for the notification. First, you need to add two Namespaces to the class:
using Windows.Data.Xml.Dom;
using Windows.UI.Notifications;
After that, we can start writing our code. Toast notifications are formatted using Xml. Because of this, we need to get a reference to the underlying Xml template for the system toast notification:
System toast notifications can hold Text (and an Image on Windows 8.1). So we need to declare the elements of the toast notification. We are using the Xml methods of the DOM namespace to get the text elements of the chosen template first:
XmlNodeList toastTextElements = xmlForToast.GetElementsByTagName("text");
toastTextElements[0].AppendChild(xmlForToast.CreateTextNode("text1"));
//additional texts, depending on the template:
//toastTextElements[1].AppendChild(xmlForToast.CreateTextNode("text2"));
//toastTextElements[2].AppendChild(xmlForToast.CreateTextNode("text3"));
This is how the image element is implemented:
XmlNodeList toastImageElement = xmlForToast.GetElementsByTagName("image");
//setting the image source uri:
if (toastImageElement != null) ((XmlElement) toastImageElement[0]).SetAttribute("src", imageSourceUri);
//setting optional alternative text for the image
if (toastImageElement != null) ((XmlElement) toastImageElement[0]).SetAttribute("alt", imageSourceAlternativeText);
You can attach local or remote images to the toast notification, but remember this works only on Windows, not on Windows Phone.
The next part we are able to set is the duration. The duration options are long (25 seconds) and short (7 seconds). The default is short, which should be ok for most scenarios. Microsoft recommends to use long only when a personal interaction of the user is needed (like in a chat). This is how we do it:
What we are doing here is to get the root element of the template’s Xml and add a new element for the duration. Now that we finally have set all options, we are able to create our toast notification and display it to the user:
ToastNotification notification = new ToastNotification(xmlForToast);
ToastNotificationManager.CreateToastNotifier().Show(notification);
the helper class
That’s all we need to do for our local notification. You might see that always rewriting the same code just makes a lot of work. Because the code for the toast notification can be called nearly everywhere in an app (it does not matter if you are calling it from a ViewModel or code behind), I wrote this helper class that makes it even more easy to use the system toast notification locally:
public class LocalToastHelper
{
public void ShowLocalToast(ToastTemplateType templateType, string toastText01, string toastText02 = null, string toastText03 = null, string imageSourceUri = null, string imageSourceAlternativeText = null, ToastDuration duration = ToastDuration.Short)
{
XmlDocument xmlForToast = ToastNotificationManager.GetTemplateContent(templateType);
XmlNodeList toastTextElements = xmlForToast.GetElementsByTagName("text");
switch (templateType)
{
case ToastTemplateType.ToastText01:
case ToastTemplateType.ToastImageAndText01:
toastTextElements[0].AppendChild(xmlForToast.CreateTextNode(toastText01));
break;
case ToastTemplateType.ToastText02:
case ToastTemplateType.ToastImageAndText02:
toastTextElements[0].AppendChild(xmlForToast.CreateTextNode(toastText01));
if (toastText02 != null)
{
toastTextElements[1].AppendChild(xmlForToast.CreateTextNode(toastText02));
}
else
{
throw new ArgumentNullException("toastText02 must not be null when using this template type");
}
;
break;
case ToastTemplateType.ToastText03:
case ToastTemplateType.ToastImageAndText03:
toastTextElements[0].AppendChild(xmlForToast.CreateTextNode(toastText01));
if (toastText02 != null)
{
toastTextElements[1].AppendChild(xmlForToast.CreateTextNode(toastText02));
}
else
{
throw new ArgumentNullException("toastText02 must not be null when using this template type");
}
;
break;
case ToastTemplateType.ToastText04:
case ToastTemplateType.ToastImageAndText04:
toastTextElements[0].AppendChild(xmlForToast.CreateTextNode(toastText01));
if (toastText02 != null)
{
toastTextElements[1].AppendChild(xmlForToast.CreateTextNode(toastText02));
}
else
{
throw new ArgumentNullException("toastText02 must not be null when using this template type");
}
;
if (toastText03 != null)
{
toastTextElements[2].AppendChild(xmlForToast.CreateTextNode(toastText03));
}
else
{
throw new ArgumentNullException("toastText03 must not be null when using this template type");
}
;
break;
}
switch (templateType)
{
case ToastTemplateType.ToastImageAndText01:
case ToastTemplateType.ToastImageAndText02:
case ToastTemplateType.ToastImageAndText03:
case ToastTemplateType.ToastImageAndText04:
if (!string.IsNullOrEmpty(imageSourceUri))
{
XmlNodeList toastImageElement = xmlForToast.GetElementsByTagName("image");
if (toastImageElement != null)
((XmlElement) toastImageElement[0]).SetAttribute("src", imageSourceUri);
}
else
{
throw new ArgumentNullException(
"imageSourceUri must not be null when using this template type");
}
if (!string.IsNullOrEmpty(imageSourceUri) && !string.IsNullOrEmpty(imageSourceAlternativeText))
{
XmlNodeList toastImageElement = xmlForToast.GetElementsByTagName("image");
if (toastImageElement != null)
((XmlElement) toastImageElement[0]).SetAttribute("alt", imageSourceAlternativeText);
}
break;
default:
break;
}
IXmlNode toastRoot = xmlForToast.SelectSingleNode("/toast");
((XmlElement) toastRoot).SetAttribute("duration", duration.ToString().ToLowerInvariant());
ToastNotification notification = new ToastNotification(xmlForToast);
ToastNotificationManager.CreateToastNotifier().Show(notification);
}
public enum ToastDuration
{
Short,
Long
}
}
As you can see, you just need to provide the wanted parameters to the ShowLocalToast method, which will do the rest of the work for you.
One word to the second switch statement I am using. The image element needs to be set only when we are using the ToastImageAndTextXX templates. There are three ways to implement the integration: using an if with 4 “or” options, the switch statement I am using or a string comparison with String.Contains. The switch statement is the cleanest option for me, so I decided to go this way. Feel free to use any of the other ways in your implementation.
In my implementation, I added also some possible ArgumentNullExceptions to make it easy to find any usage errors.
For your convenience, I attached the source file. Just swap out the namespace with yours. Download
The usage of the class is pretty simple:
var _toastHelper = new LocalToastHelper();
_toastHelper.ShowLocalToast(ToastTemplateType.ToastText02, "This is text 1", "This is text 2");
audio options
The system toasts have another option that can be set: the toast audio. This way, you can customize the appearance of the toast a bit more. I did not implement it yet, because there are some more options and things to remind, and I haven’t checked them out all together. Once I did, I will add a second post to this one with the new information.
As always, I hope this is helpful for some of you.
In case you missed it, I lately am deeply diving into MVVM. Earlier today, I wanted to implement the well loved feature that a search is performed by pressing the Enter button. Of course, this would be very easy to achieve in code behind using the KeyUpEvent (or the KeyDownEvent, if you prefer).
However, in MVVM, especially in a Universal app, this is a bit trickier. We need to route the event manually to our matching command. There are surely more ways to achieve it, but I decided to use the Behaviors SDK to achieve my goal. The first step is of course downloading the matching extension (if you haven’t done so before). To do so, click on TOOLS/Extensions and Updates in Visual Studio and install the Behaviors SDK from the list:
The next step we need to do is to add a new Converter (I added it to the common folder, you may change this to your preferred place). As we are hooking up the KeyUpEventArgs, I called it KeyUpEventArgsConverter. After you created the class, implement the IValueConverter interface. You should now have a Convert and a ConvertBack method. We are just adding two lines of code to the Convert method:
var args = (KeyRoutedEventArgs)value;
return args;
That’s it for the Converter. Save the class and build the project. For the next step, we need to go to our View where the Converter should do its work. Before we can use it, we need to give our Converter a key to be identified by the Binding engine. You can do this app wide in App.xaml, or in your page:
With the EventTriggerBehavior, we are able to hook into the desired event of a control. We then only need to bind to a Command in our ViewModel and tell the Behaviors SDK that it should route the “KeyUp” event using our Converter.
Let’s have a final look at the command that handles the event:
public RelayCommand<KeyRoutedEventArgs> SearchTermKeyEventArgsCommand
{
get
{
return _searchTermKeyEventArgsCommand
?? (_searchTermKeyEventArgsCommand = new RelayCommand<KeyRoutedEventArgs>(
p =>
{
if (p.Key == Windows.System.VirtualKey.Enter)
{
//your code here
}
}));
}
}
As you can see, we are using a Command that is able to take a Generic (in my case it comes from the MVVM Light Toolkit, but there are several other version floating around). Because of this, we are finally getting the KeyRoutedEventArgs into our ViewModel and are able to use its data and properties.
The VirtualKey Enumeration holds a reference to a lot of (if not all) keys and works for both hardware and virtual keyboards. This makes this code safe to use in an Universal app.
As I am quite new to MVVM, I am not entirely sure if this way is the “best” way, but it works as expected with little efforts. I hope this will be useful for some of you.
Useful links that helped me on my way to find this solution: