Metro Tile Notifications in C# - c#

I'm trying to put together a simple Windows 8 metro style app in c# with tile notifications but I can't seem to get them working.
What I can't quite figure out yet is where the code to update the tile notifications should reside. I've had a look at the Javascript sample, but I'm not seeing how that works in a C# app. Has anyone got some sample code or a quick tip on where tile updates should happen in a C# metro app?

My understanding is that every app decides where to do this for itself. Normally, you'd do it whenever you're also updating your normal UI with the same data - e.g. if your app is an RSS reader, and you've just downloaded a new item to display, that's where you also update your tile by posting a notification. In the sample JavaScript app, this is done from event handlers for controls for the sake of convenience.
As for the code to change the tile, it should be almost identical to JavaScript version, since in both cases you use Windows.UI.Notifications namespace. Following is a very simple C# app that updates the tile when you click the button. XAML:
<UserControl x:Class="TileNotificationCS.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
d:DesignHeight="768" d:DesignWidth="1366">
<StackPanel x:Name="LayoutRoot" Background="#FF0C0C0C">
<TextBox x:Name="message"/>
<Button x:Name="changeTile" Content="Change Tile" Click="changeTile_Click" />
</StackPanel>
</UserControl>
and code behind:
using System;
using Windows.Data.Xml.Dom;
using Windows.UI.Notifications;
using Windows.UI.Xaml;
namespace TileNotificationCS
{
partial class MainPage
{
TileUpdater tileUpdater = TileUpdateManager.CreateTileUpdaterForApplication();
public MainPage()
{
InitializeComponent();
}
private void changeTile_Click(object sender, RoutedEventArgs e)
{
XmlDocument tileXml = TileUpdateManager.GetTemplateContent(TileTemplateType.TileWideText01);
XmlElement textElement = (XmlElement)tileXml.GetElementsByTagName("text")[0];
textElement.AppendChild(tileXml.CreateTextNode(message.Text));
tileUpdater.Update(new TileNotification(tileXml));
}
}
}
Don't forget that you need a wide tile for text to show up - to get it, set some image for "Wide Logo" in Package.appxmanifest.

Make sure you change the Initial rotation to Landscape, set some image for Widelogo, and use this method to set the text along with an expiry.
void SendTileTextNotification(string text, int secondsExpire)
{
// Get a filled in version of the template by using getTemplateContent
var tileXml = TileUpdateManager.GetTemplateContent(TileTemplateType.TileWideText03);
// You will need to look at the template documentation to know how many text fields a particular template has
// get the text attributes for this template and fill them in
var tileAttributes = tileXml.GetElementsByTagName("text");
tileAttributes[0].AppendChild(tileXml.CreateTextNode(text));
// create the notification from the XML
var tileNotification = new TileNotification(tileXml);
// send the notification to the app's default tile
TileUpdateManager.CreateTileUpdaterForApplication().Update(tileNotification);
}
Here is a detailed explanation http://www.amazedsaint.com/2011/09/hellotiles-simple-c-xaml-application.html

Related

How to inject a MVVM view into a region of a shell UWP Page

I am creating an application that has a navigation bar along the top, and large touchscreen sidebar buttons down both sides to perform functions. I need the content in the middle "Main Content" area to change based on with "page" the navigation bar is displaying. I am looking for a way to be able to use an MVVM format, and have my different views injected into this main content area without having to change the shell view of my application which holds all the navigation bar and buttons.
I know PRISM has some sort of way to do region management but i was wondering if there is a way to do this without an external library or with MVVM-light which I have already implemented elsewhere.
This is a Windows 10 UWP Application built for the 1809 creators update. Thusfar, I have tried the way that currently works on WPF whereas you have a datatemplate for each ViewModel and in that datatemplate it simple displays a UserControl which is your View.
Then using a ContentControl element I can bind to the current datacontext of the application to have it switch between different views by purely changing the datacontext.
I tried this same method on UWP with no success. It simply displays the string object name of the View I am trying to display instead of the usercontrol I have defined.
(TestView.xaml)I created a simple userControl called "TestView"
<Grid Background="Red">
<Rectangle Margin="50" Fill="White"/>
</Grid>
(TestViewModel.cs)I also have a empty ViewModel for the View
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Views;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace UIMockUp2.ViewModels
{
public class TestViewModel : ViewModelBase
{
}
}
(MainPage.xaml)In the page resources I have a data template
<Page.Resources>
<DataTemplate x:DataType="data:TestViewModel" x:Key="TestTemplate">
<views:TestView/>
</DataTemplate>
</Page.Resources>
(MainPage.xaml)I also have the contentControl bind to the current dataContext
<ContentControl Content="{Binding}"/>
(MainPage.xaml.cs)Finally in the code behind I have a button that just sets the data context
private void TestView_Clicked(object sender, RoutedEventArgs e)
{
DataContext = new TestViewModel();
}
In WPF it will then update the grid region that I have the Content Control in with the userControl but in UWP in doesn't. Any help would be much appreciated in finding a way to do this!
Take a look at the Windows Template Studio in Visual studio. This should cover the specific issue you are looking at with navigation, and shell content. https://marketplace.visualstudio.com/items?itemName=WASTeamAccount.WindowsTemplateStudio
To answer my own question, there are several ways to do this! After MUCH exploring I have discovered a way that is better for my particular application. However, #Going-gone's solution is still great for a template framework of an app!
For a very simple and straightforward way here is what I did.
In my ShellPage, I defined a Grid and sectioned up the middle section to be for my Main Content which is the part the changes.
(ShellPageView.xaml)
<Grid x:Name="Video" Grid.Row="1" Grid.Column="1">
<Frame x:Name="MainContentRegion" Margin="5" Content="{Binding CurrentPage}"/>
</Grid>
Then all you have to do in your ViewModel is have a CurrentPage variable that was binded to in the xaml View. And change what view that points to.
(ShellPageViewModel.cs)
private Page _currentPage;
public Page CurrentPage
{
get { return _currentPage; }
set
{
_currentPage = value;
RaisePropertyChanged();
}
}
public void GoToSettingsPage()
{
CurrentPage = new SettingsView();
}
I use commands with other navigation buttons on the shell page to trigger this command. If you have any other questions on how to use this method, let me know!

How to embed web application into windows app with custom behavior

I need to embed a standard webapp inside a windows app container.
The container just needs to be a wrapper around a webkit or similar rendering engine (I would like to avoid using IE rendering engine if possible) and it would contain some minimal window management logic - things like being borderless with no titlebars, being able to fix position and size, and custom overlay/always-on-top rules based on currently focused window.
I've been looking at node-webkit and it seems to fit the bill as far as containing a webapp is concerned, but I'm not sure I would be able to do the latter.
Can this be done with node-webkit, is there some other approach that would fit my use case better? I have absolutely no idea how windows app development is done, so I would appreciate some help.
If you are using WPF, you can create you window with something like this (xaml):
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
WindowStyle="None"
Title="MainWindow" Left="100" Top="200" Height="350" Width="525" PreviewKeyDown="Window_PreviewKeyDown">
<Grid x:Name="grdBrowserHost">
</Grid>
</Window>
WindowStyle attr None means "borderless with no titlebars" window. Left and Top are for position, and Width and Height are self-explanatory. All those properties can be accessed via code-behind with simple this.Width, etc... PreviewKeyDown I put here because in this example (as you will see), Topmost property will be changed from code behind (dynamically).
Code-behind should look something like
using System;
using System.Windows;
using System.Windows.Input;
namespace WpfApplication2
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
System.Windows.Controls.WebBrowser browser = new System.Windows.Controls.WebBrowser();
// you can put any other uri here, or better make browser field and navigate to desired uri on some event
browser.Navigate(new Uri("http://www.blic.rs/"));
grdBrowserHost.Children.Add(browser);
}
private void Window_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Escape)
{
this.Close();
}
else
{
this.Topmost = !this.Topmost;
}
}
}
}
In this example I have created default WebBrowser control for showing html. If you want some other web rendering engine you must find 3rd-part control and include it in your references. For webkit, you can check How to use WebKit browser control in WPF
What you need is "UWP Bridge for web apps" ;-)
Look in the Windows Dev Center:
UWP Bridge for web apps - Create your app now

Animated Gifs with Imagetools, in WP7 c#

Well, This has been solved. I don't know if it was a glitch on my end or if ImageTools was just a pain to set up accordingly. Thank you for the answers everyone, and they very likely all work. The once I marked as answered does indeed work, BUT HERE IS HOW:
(Credits go to Patrick for sticking with this, and his code is used as
noted below.)
(Also, big thanks to everyone else too who submitted something. Sorry
if my noobness scared you all away)
To get an animated Gif to work in your wp7 7.1 app, do these steps:
1) Download ImageTools (I used latest version at the time (0.3)) http://imagetools.codeplex.com/downloads/get/156530
2) Unstuff the file, and in the "Bin > Phone" folder just throw ALL* the dll file extensions into your wp7 app folder. The other files (xml/pdb) don't need to be added. (*this step is extra work, and we will be removing these extra dlls later on, but hell it'll save a headache.)
3) Add the references to your wp7 app in the Solution Explorer window > References folder drop down. To do that, right click the References folder, click "Add Reference" and browse to the dll files. Repeat this process. (Referencing all those dlls is 1 minute of the extra 2 mins of work ultimately, but you shouldn't get any errors when compiling)
4) Now on the xaml page you want to add the image to, add this at the top in your header code:
xmlns:it="clr-namespace:ImageTools.Controls;assembly=ImageTools.Controls"
xmlns:vm="clr-namespace:GifViewer.ViewModels"
NOTICE: Change "GifViewer" to your application name.
5) On that same page, just below it, add in this code:
<phone:PhoneApplicationPage.DataContext>
<vm:MainViewModel/>
</phone:PhoneApplicationPage.DataContext>
<Grid x:Name="LayoutRoot" Background="Transparent">
<it:AnimatedImage Source="{Binding AnimationImage}" />
</Grid>
NOTICE: Doesn't have to be a grid. Doesn't have to be in anything at all. It can stand alone.
6) The accepted answer has a folder in the app called "ViewModels" and in it is a custom class titled "MainViewModel" So in the solution explorer or in the desktop, add a folder called ViewModels and make a c# class page titled MainViewModel. Move that into that folder, and refresh the solution explorer. If you cannot see the file, you need to click the "Show all files" button just under the Solution Explorer Header.
7) Using the accepted answer below, in the "MainViewModel.cs" class page, add the following just below the others:
using ImageTools;
using ImageTools.Controls;
using ImageTools.IO;
using ImageTools.IO.Gif;
8) The accepted answer uses this code. Change "GifViewer" to your application name when copying this code, and also change the Uri location of the gif. In my example, I have a folder named "Gif" and in it is "explosion.gif". Build Action can be kept as Resource by default.
namespace GifViewer.ViewModels {
public class MainViewModel : DependencyObject {
public MainViewModel() {
Decoders.AddDecoder<GifDecoder>();
Uri uri = new Uri("Gif/explosion.gif", UriKind.Relative);
ExtendedImage image = new ExtendedImage();
// either of these two method work.
// Just remove the first / to switch
//*
image.LoadingCompleted +=
(o, e) => Dispatcher.BeginInvoke(() => AnimationImage = image);
image.UriSource = uri;
/*/
Stream stream = Application.GetResourceStream(uri).Stream;
GifDecoder decoder = new GifDecoder();
decoder.Decode(image, stream);
AnimationImage = image;
/**/
}
public static readonly DependencyProperty AnimationImageProperty =
DependencyProperty.Register("AnimationImage",
typeof(ExtendedImage),
typeof(MainViewModel),
new PropertyMetadata(default(ExtendedImage)));
public ExtendedImage AnimationImage {
get { return (ExtendedImage)GetValue(AnimationImageProperty); }
set { SetValue(AnimationImageProperty, value); }
}
}
}
Go ahead and compile. You might get a runtime error indicating that
couldn't load, but running the application should get rid of it.
Your gif should now play.
9) Start removing the EXTRA dll references which aren't needed (the other minute of the 2 mins of extra work). Basically, all you want referenced is:
ImageTools
ImageTools.Controls
ImageRools.IO.Gif
ImageTools.Controls might not even be needed, but the file size is like 25kb and honestly I couldn't get the gif to show if I removed it.
There you go!
Original Question I asked
I am having the worst headache trying to get my animated gif to play in my WP7 app. I simply cannot connect the dots to make this happen, despite having imagetools and viewing the current "solutions" on stackoverflow/the web.
My problem is outlined below, but for reference I have looked at:
Display GIF in a WP7 application with Silverlight
and http://blog.naviso.fr/wordpress/?p=733
So how does one actually set this blasted thing up to display animated gifs in a wp7 app!? Question in specific -- Is this the correct code to get my animated gif to appear? If not, what below needs to be fixed?
My animated gif file location on the phone (NOT from internet):
Gif/explosion.gif
Main Xaml page:
xmlns:imagetools="clr-namespace:ImageTools.Controls;assembly=ImageTools.Controls"
....
<phone:PhoneApplicationPage.Resources>
<imagetools:ImageConverter x:Key="ImageConverter" />
</phone:PhoneApplicationPage.Resources>
....
<imagetools:AnimatedImage x:Name="animationgif" Source="{Binding ImageSource, Converter={StaticResource ImageConverter}}" />
and the code behind for the xaml page:
public partial class MainPage : PhoneApplicationPage
{
using ImageTools;
using ImageTools.Controls;
using ImageTools.IO.Gif;
public MainPage()
{
InitializeComponent();
ImageTools.IO.Decoders.AddDecoder<ImageTools.IO.Gif.GifDecoder>();
}
public void eventtofiretoshowexplosion_gif(object sender, MouseButtonEventArgs e)
{
// A main problem -- this code doesn't work by itself, as what is the ImageSource!?
// It cannot be used as a variable it says.
// animationgif.ImageSource does not work at all (not a method).
ImageSource = new Uri("http://mysite/my.gif", UriKind.Absolute);
}
}
This has been bugging me for the past few hours, and I really could use some help with this. If there is a quick fix to this, please help out and show how it is done instead of guiding me to a page. I've seen FAR too many pages about this, and while each one claims to work, it just cannot in my app.
It seems the Build Action of your image is incorrect, so the application can't "find" the resource.
You have two options. Either set the build action to content, or set it as resource and specify "copy if newer".
Open your solution explorer
Open your properties window
Click on your image
Set Build action to Resource and Copy to output directory Copy if newer
Further reading: Resources in WPF – I (Binary Resources)
I put together a small example using a viewmodel which seems to work given the above resource "requirement". I hope you might find it useful. The viewmodel class is in a folder called ViewModels.
using System;
using System.IO;
using System.Windows;
using ImageTools;
using ImageTools.IO;
using ImageTools.IO.Gif;
namespace GifViewer.ViewModels {
public class MainViewModel : DependencyObject {
public MainViewModel() {
Decoders.AddDecoder<GifDecoder>();
Uri uri = new Uri("Gif/explosion.gif", UriKind.Relative);
ExtendedImage image = new ExtendedImage();
// either of these two method work.
// Just remove the first / to switch
//*
image.LoadingCompleted +=
(o, e) => Dispatcher.BeginInvoke(() => AnimationImage = image);
image.UriSource = uri;
/*/
Stream stream = Application.GetResourceStream(uri).Stream;
GifDecoder decoder = new GifDecoder();
decoder.Decode(image, stream);
AnimationImage = image;
/**/
}
public static readonly DependencyProperty AnimationImageProperty =
DependencyProperty.Register("AnimationImage",
typeof(ExtendedImage),
typeof(MainViewModel),
new PropertyMetadata(default(ExtendedImage)));
public ExtendedImage AnimationImage {
get { return (ExtendedImage)GetValue(AnimationImageProperty); }
set { SetValue(AnimationImageProperty, value); }
}
}
}
and the xaml
<phone:PhoneApplicationPage
x:Class="GifViewer.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:it="clr-namespace:ImageTools.Controls;assembly=ImageTools.Controls"
xmlns:vm="clr-namespace:GifViewer.ViewModels"
mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
shell:SystemTray.IsVisible="True">
<phone:PhoneApplicationPage.DataContext>
<vm:MainViewModel/>
</phone:PhoneApplicationPage.DataContext>
<Grid x:Name="LayoutRoot" Background="Transparent">
<it:AnimatedImage Source="{Binding AnimationImage}" />
</Grid>
</phone:PhoneApplicationPage>
When using AnimatedImage your source binding has to return ExtendedImage. ExtendedImage class is basically the "BitmapImage" equivalent of the normal Image control.

How can I use DesignData to help develop a Metro app?

I've been merrily using the DesignData in Windows Phone apps, and I was hoping to use it to help visualise designs in a Metro style app in VS2012/Blend for VS.
I've tried the hopefully obvious:
<common:LayoutAwarePage
x:Name="pageRoot"
x:Class="MyRootNamespace.Views.EventView"
DataContext="{Binding DefaultViewModel, RelativeSource={RelativeSource Self}}"
IsTabStop="false"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MyRootNamespace.Views"
xmlns:common="using:MyRootNamespace.Common"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:bm="using:Bing.Maps"
d:DataContext="{d:DesignData Source=../SampleData/SpecialEventSampleData.xaml}"
mc:Ignorable="d">
With the SpecialEventSampleData.xaml looking loosely like:
<local:SpecialEvent
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MyRootNamespace.ViewModels"
EventName="Foo Fighters"
Description="This exclusive April Fools Gig will see Dave Grohl and the rest of the Foo Fighters rock out at this exclusive made up gig"
VenueName="Village Hall"
/>
The class to which it refers has a public, parameterless constructor, but Visual Studio is giving an error:
Error Cannot create an instance of "SpecialEvent". C:...\MyRootNamespace.Windows\SampleData\SpecialEventSampleData.xaml
In addition, I was expecting to have to set the build action to "DesignData", or similar, but this doesn't appear to be an option in Visual Studio 2012?
What do I need to do to be able to get design time data to work in VS2012/Blend?
Is SpecialEvent your ViewModel? If so, can you do something like this in your XAML (directly after your common:LayoutAwarePage opening declaration)?
<d:Page.DataContext>
<local:SpecialEvent>
</d:Page.DataContext>
And then remove this line from your common:LayoutAwarePage:
d:DataContext="{d:DesignData Source=../SampleData/SpecialEventSampleData.xaml}"
I have code similar to this that is working.
In Windows Phone (I believe) the path to the sample data file is relative to the application root. In Windows 8, the path to the sample data file is relative to the page xaml file you want to use it in.
In your sample above, the page.xaml file would need to be in a sub-folder of the project but in a different folder than SampleData.
Windows 8 sample data does not automatically create collection instances for you. So, if you have sample data like this:
<Event>
<Attendees>
<Attendee Name="Joe" />
</Attendees>
</Event>
you would need to make sure that the backing field for the Attendees property is set to a new collection instance when you define the variable. If you are using automatic properties (Attendees { get; set; } syntax) you will need to set the property to a new collection instance in the constructor before items can be added in xaml.
Finaly, Windows 8 xaml cannot handle generic types. So, if your Attendees property is of type Collection<Attendee> you will not be able to create an instance of it in xaml.
You can always make a simple class called AttendeeCollection that inherits from Collection<Attendee> and create instances of that in your xaml instead.
Hope that helps.
Try full path to the xaml file instead of relative.
This is a touch obscure, but it boils down to the implementation I had of INotifyPropertyChanged on my View-Model.
In my Windows Phone code, I have to go to a small amount of effort to ensure that the events raised by background worker threads pop out on the UI thread:
protected delegate void OnUIThreadDelegate();
protected void OnUIThread(OnUIThreadDelegate onUIThreadDelegate)
{
if (Deployment.Current.Dispatcher.CheckAccess())
{
onUIThreadDelegate();
}
else
{
Deployment.Current.Dispatcher.BeginInvoke(onUIThreadDelegate);
}
}
This was then used:
protected override void OnPropertyChanged(PropertyChangedEventArgs e)
{
OnUIThread(() =>
{
base.OnPropertyChanged(e);
});
}
It appears that when porting that code, I was not checking the result of CoreWindow.GetForCurrentThread() which was causing an exception to fire deep in the darkest depths of the code, as the designer was setting the properties on my type, and I was trying to raise the events and dying horribly instead. My bad.

Creating a Converter to take an ID and create an Image in Silverlight

I am using a WCF weather service and receiving weather information like ID, Description, and Images. It returns like this:
<WeatherDescription>
<WeatherID>1</WeatherID>
<Description>Thunder Storms</Description>
<PictureURL>
http://ws.cdyne.com/WeatherWS/Images/thunderstorms.gif
</PictureURL>
</WeatherDescription>
Now in the XAML I am showing my data in a dataGrid as so:
<sdk:DataGridTextColumn Header="ID" Binding="{Binding WeatherID}" />
The above binding is to another function of the service that returns a 7 day forecast but returns the same weather ID that works with the weather description. I created an array of all the Weather Descriptions on the code side like so:
public partial class MainPage : UserControl
{
//array of weather descriptions
private WeatherDescription[] weatherInformation;
WeatherSoapClient weatherClient = new WeatherSoapClient();
public MainPage()
{
InitializeComponent();
weatherClient.GetWeatherInformationCompleted += new EventHandler<GetWeatherInformationCompletedEventArgs>(weatherClient_GetWeatherInformationCompleted);
weatherClient.GetWeatherInformationAsync();
}
void weatherClient_GetWeatherInformationCompleted(object sender, GetWeatherInformationCompletedEventArgs e)
{
weatherInformation = e.Result;
}
}
What I want to do is create a converter that takes the ID from that Column and converts it to an image using the URL supplied in the weather descriptions.
I know Silverlight does not support GIF's so I would like to send that image to a handler that would convert it to a JPG.
Being brand new to both Silverlight and C# these are two things that I am really having trouble with. Thank you for the help in advance! And code snippets are the best help for me since I do not understand a lot of C# yet.
For the converter, you can do something like this:
<sdk:DataGrid>
<sdk:DataGrid.Resources>
<local:WeatherIdToImageConverter key="IdToImageConverter" />
</sdk:DataGrid.Resources>
...
<sdk:DataGridTemplateColumn>
<sdk:CellTemplate>
<DataTemplate>
<Image Source="{Binding WeatherID, Converter={StaticResource IdToImageConverter}}" />
...
In your implementation of the converter, I would use the ImageTools library (http://imagetools.codeplex.com/) to convert between GIF and PNG (PNG will be better quality than JPEG).

Categories