I was using the following code to show a Windows 10 Toast notifications from a .NetCore 3.1 console application, where I was using objects from the following namespaces: Windows.UI.Notifications & Windows.Data.Xml.Dom, in .Net5.0 these namespaces seem to be moved to somewhere else.
public void GenerateToast(string appid, string imageFullPath, string h1, string h2, string p1)
{
try
{
var template = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastImageAndText04);
var textNodes = template.GetElementsByTagName("text");
textNodes[0].AppendChild(template.CreateTextNode(h1));
textNodes[1].AppendChild(template.CreateTextNode(h2));
textNodes[2].AppendChild(template.CreateTextNode(p1));
if (File.Exists(imageFullPath))
{
XmlNodeList toastImageElements = template.GetElementsByTagName("image");
((XmlElement)toastImageElements[0]).SetAttribute("src", imageFullPath);
}
IXmlNode toastNode = template.SelectSingleNode("/toast");
((XmlElement)toastNode).SetAttribute("duration", "long");
var notifier = ToastNotificationManager.CreateToastNotifier(appid);
var notification = new ToastNotification(template);
notifier.Show(notification);
}
catch (Exception)
{
// Ignore
}
}
How to get back these namespaces?
Solution found Here:
This option is only supported in projects that use .NET 5 (or a later release) and target Windows 10, version 1809 or a later OS release. For more background info about this scenario, see this blog post.
With your project open in Visual Studio, right-click your project in
Solution Explorer and choose Edit Project File. Your project file
should look similar to this.
WinExe
net5.0
true
Replace the value of the TargetFramework element with one of the
following strings:
net5.0-windows10.0.17763.0: Use this value if your app targets
Windows 10, version 1809. net5.0-windows10.0.18362.0: Use this value
if your app targets Windows 10, version 1903.
net5.0-windows10.0.19041.0: Use this value if your app targets
Windows 10, version 2004.
For example, the following element is for a project that targets
Windows 10, version 2004.
net5.0-windows10.0.19041.0
Save your changes and close the project file.
Related
I am building a UWP application. When I open the app settings for my App, I want to display the Version number of my application in the Specifications section.
For example- In the following image, you can see the version number as 1.2.4.0 under the Specifications section in the App settings. How can I do a similar thing for my UWP application.
Image
How can I achieve this?
See: Retrieve the Current App version from Package
That's how you can display it anyway.
public string GetAppVersion()
{
Package package = Package.Current;
PackageId packageId = package.Id;
PackageVersion version = packageId.Version;
return "Version " + string.Format("{0}.{1}.{2}.{3}", version.Major, version.Minor, version.Build, version.Revision);
}
The UWP Community Toolkit has a SystemInformation class which has many relevant properties and methods.
You could use it to get the information that you want.
For example,
// To get application's name:
public string ApplicationName => SystemInformation.ApplicationName;
// To get application's version:
public string ApplicationVersion => $"{SystemInformation.ApplicationVersion.Major}.{SystemInformation.ApplicationVersion.Minor}.{SystemInformation.ApplicationVersion.Build}.{SystemInformation.ApplicationVersion.Revision}";
You get this for free, nothing special needs to be done. The App settings page will display the version number retrieved from your appxmanifest file.
I've searched through a number of different posts to do with creating toast notifications from a Win Form however when these through I get an error when generating the toast notification.
System.Exception: Element not found. (Exception from
HRESULT:0x80070490).
I have edited the csproj file and added the following:
<PropertyGroup>
<TargetPlatformVersion>10.0.10586</TargetPlatformVersion>
</PropertyGroup>
and added the references to Windows.Data and Windows.UI and also a reference to System.Runtime.dll as per the suggestions in Windows.UI.Notifications is missing
using Windows.Data.Xml.Dom;
using Windows.UI.Notifications;
using System.Windows.Forms;
using System;
namespace ToastNotify
{
class Notify
{
public void GenerateToast(string header, string content)
{
ToastTemplateType toastTemplate = ToastTemplateType.ToastImageAndText02;
XmlDocument toastXml = ToastNotificationManager.GetTemplateContent(toastTemplate);
XmlNodeList toastTextElements = toastXml.GetElementsByTagName("text");
toastTextElements[0].AppendChild(toastXml.CreateTextNode(header));
toastTextElements[1].AppendChild(toastXml.CreateTextNode(content));
XmlNodeList toastImageElements = toastXml.GetElementsByTagName("image");
((XmlElement)toastImageElements[0]).SetAttribute("src", "..\\..\\Resources\\icon.ico");
IXmlNode toastNode = toastXml.SelectSingleNode("/toast");
((XmlElement)toastNode).SetAttribute("duration", "long");
ToastNotification toast = new ToastNotification(toastXml);
try
{
ToastNotificationManager.CreateToastNotifier().Show(toast);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
}
}
Any suggestions as to where I am going wrong?
You should explicitly provide applicationId for CreateToastNotifier.
Like this:
private const String APP_ID = "Microsoft.Samples.DesktopToastsSample";
...
ToastNotificationManager.CreateToastNotifier(APP_ID).Show(toast);
But I have bad news. Starting from Windows 10 1709 WinForms applications just does not show toast notifications. Before that Show(toast) was working, but now it neither throw an exception, nor show any toast notification.
I'm still figuring this out.
As noted by Prateek Shrivastava there are (new) limitations.
Have a look here https://learn.microsoft.com/en-us/uwp/api/windows.ui.notifications.toastnotificationmanager.createtoastnotifier
Update:
Here is the step by step guide, to create a setup with APP_ID so notifications will work on all Windows 10 versions:
Send a local toast notification from desktop C# apps
Update:
It works again in Windows 10 1903 without setup.
Use This and make sure you are setting the Image (Icon) full path if you want to show an icon otherwise just pass null.
public static void GenerateToast(string appid, string imageFullPath, string h1, string h2, string p1)
{
var template = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastImageAndText04);
var textNodes = template.GetElementsByTagName("text");
textNodes[0].AppendChild(template.CreateTextNode(h1));
textNodes[1].AppendChild(template.CreateTextNode(h2));
textNodes[2].AppendChild(template.CreateTextNode(p1));
if (File.Exists(imageFullPath))
{
XmlNodeList toastImageElements = template.GetElementsByTagName("image");
((XmlElement)toastImageElements[0]).SetAttribute("src", imageFullPath);
}
IXmlNode toastNode = template.SelectSingleNode("/toast");
((XmlElement)toastNode).SetAttribute("duration", "long");
var notifier = ToastNotificationManager.CreateToastNotifier(appid);
var notification = new ToastNotification(template);
notifier.Show(notification);
}
I need to chime in here, because I'm working on a WinForms app (.Net Framework 4.7*) that's failing to build on a GitHub build worker because at some point, support for toast notifications was hacked in with some weird references to these WinMetadata\Windows.*.winmd files.
Woe be to anyone who has found this StackOverflow question.
You're probably targeting the .Net Framework 4.x because you're working on a Win Forms app. .Net Framework 4.8 is supported on Windows 7, and Windows 7 does not have ToastNotifications which is probably the class you're looking for. Hence the problem.
I think the only solution is the one in the updated answer that's most upvoted, which is just target the more modern UWP framework that will only work on Windows 10 and up. But you're still trying to send toast notifications from a framework that's not designed to support it. At some point in your code, you're probably doing a check if the platform you're running on is Windows 10 or newer. Not even a compiler statement, just straight up C# or VB.Net. That's not how the .Net Framework is designed to work - it's meant to be platform-agnostic.
My only advice is; setup a new build target for Windows 10+ and setup your project following the advice from Stephen. That should be the least-hackish way of making WinForms do neat Windows 10 tricks.
I am trying to add a MapIcon to my Bing maps control. When I am running the application in my debugging environment on visual studio I don't have any issues. However once I build my app package and run it, adding a map Icon crashes the application and throws this an exception that reads:
"Unable to cast object of type Windows.UI.Xaml.Controls.Maps.MapIcon to type Windows.UI.Xaml.Controls.Maps.IMapElement4"
Here is the simple code that instantiates the MapIcon. It is important to know that I do not have any issues adding these map Icons in debug mode. The problem only exists once the app package has been built and run. I was able to pinpoint the exception using a try/catch to display the exception while the released app is running. If anyone can help me to get rid of this exception, or have any advice for a work around, it would be much appreciated
MapIcon messageicon2_2 = new MapIcon
{
Location = message_position,
NormalizedAnchorPoint = new Point(0.5, 1.0),
ZIndex = 0,
Title = "msg " + count + "(2.2)",
IsEnabled = true,
CollisionBehaviorDesired = MapElementCollisionBehavior.RemainVisible
};
MyWaypoints.Add(messageicon2_2);
messageLayer.MapElements = MyWaypoints;
[EDIT To Clarify]: I know that this bug is coming specifically from the instantiation of the Mapicon. This code works perfectly fine when it is released and run on a Windows 10 17134 machine.... The machine that I need it to run is Windows 10 16299. This machine can not be updated to a newer version of windows. I am in need of a way to display these map icons on this older release of windows.
The exception points to the IsEnabled property which was added to MapElement for Windows OS Version 1803 (17134). See MapElement.IsEnabled Property.
I know the exception is not the most helpful, but maybe there was some other warning about it that got missed?
For errors like this, you can either remove all uses of the missing API and/or make sure to write version adaptive code that can run on the lowest OS version, while also taking advantage of the selected features that are available only on certain OS versions.
Specifically you can do something like:
var messageicon2_2= new MapIcon
{
Location = message_position,
NormalizedAnchorPoint = new Point(0.5, 1.0),
ZIndex = 0,
Title = "msg " + count + "(2.2)",
CollisionBehaviorDesired = MapElementCollisionBehavior.RemainVisible
};
if (ApiInformation.IsPropertyPresent("Windows.UI.Xaml.Controls.Maps.MapElement", "IsEnabled"))
{
messageicon2_2.IsEnabled = true;
}
MyWaypoints.Add(messageicon2_2);
messageLayer.MapElements = MyWaypoints;
I am trying to reference "Windows.Networking.Connectivity" classes in my desktop application. I am basically interested in handling metered connections in my app.
Basically what I am trying to do is simple:
var connectionCost = NetworkInformation.GetInternetConnectionProfile().GetConnectionCost();
if (connectionCost.NetworkCostType == NetworkCostType.Unknown
|| connectionCost.NetworkCostType == NetworkCostType.Unrestricted)
{
//Connection cost is unknown/unrestricted
}
else
{
//Metered Network
}
The only method I know of that allows a desktop application to reference UWP assemblies is by manually editing the project file and adding the following line to the csproj file:
<TargetPlatformVersion>8.0</TargetPlatformVersion>
Applying the code and "hack" works fine but the problem is that doing so will prevent my app from running on Windows 7 which I need to support.
I was wondering if there is a way to reference UWP assemblies in a desktop application without having to drop support for Windows 7.
And since for the time being I only want to check if a connection is metered, I am open to suggestions about how to get this information without referencing Windows assemblies.
I found a way to use reflection and call UWP methods without having to specify a target platform. For my case this is what I did:
var networkInfoType = Type.GetType("Windows.Networking.Connectivity.NetworkInformation, Windows, ContentType=WindowsRuntime");
var profileType = Type.GetType("Windows.Networking.Connectivity.NetworkInformation, Windows, ContentType=WindowsRuntime");
var profileObj = networkInfoType.GetTypeInfo().GetDeclaredMethod("GetInternetConnectionProfile").Invoke(null, null);
dynamic profDyn = profileObj;
var costObj = profDyn.GetConnectionCost();
dynamic dynCost = costObj;
var costType = (NetworkCostType)dynCost.NetworkCostType;
if (costType == NetworkCostType.Unknown
|| costType == NetworkCostType.Unrestricted)
{
//Connection cost is unknown/unrestricted
}
else
{
//Metered Network
}
I'm developing a program in C# (Visual Studio 2015) and I want to show a toast message to the user at a certain situation. I downloaded this code from the MSDN and it runs fine:
// Get a toast XML template
XmlDocument toastXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastImageAndText04);
// Fill in the text elements
XmlNodeList stringElements = toastXml.GetElementsByTagName("text");
for (int i = 0; i < stringElements.Length; i++)
{
stringElements[i].AppendChild(toastXml.CreateTextNode("Line " + i));
}
// Specify the absolute path to an image
String imagePath = "file:///" + Path.GetFullPath("toastImageAndText.png");
XmlNodeList imageElements = toastXml.GetElementsByTagName("image");
imageElements[0].Attributes.GetNamedItem("src").NodeValue = imagePath;
// Create the toast and attach event listeners
ToastNotification toast = new ToastNotification(toastXml);
toast.Activated += ToastActivated;
toast.Dismissed += ToastDismissed;
toast.Failed += ToastFailed;
// Show the toast. Be sure to specify the AppUserModelId on your application's shortcut!
ToastNotificationManager.CreateToastNotifier(APP_ID).Show(toast);
After testing this code I wanted to implement it into my application. So I changed it up a little bit and tried to run it. The error messages:
The type "IReadOnlyList<>" is defined in a not referenced assembly. Add a reference to System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
(translated)
Same goes for IEnumerable<> and IReadOnlyList<>
The error come from these two lines:
for (int i = 0; i < stringElements.Length; i++)
{
stringElements[i].AppendChild(toastXml.CreateTextNode("Line " + i));
I also tried adding the reference to System.Runtime. I downloaded it with NuGet (https://www.nuget.org/packages/System.Runtime/4.0.0/).
After that the errors were gone, but now literaly every word in my code is cringled red with error like "System.Object is not defined" and so on (but it still runs when I start it!).
The only possible solution I can think of is that System.Runtime is already installed somewhere on my computer, and that 4.0.0 is the wrong version for my program. But I can't find it anywhere.
PS: It's a desktop-application, not a Windows-Store application.
I think it is the same problem as in this question
You must add a reference to
C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.1\Facades\System.Runtime.dll
PS : If you have a Windows 10 only desktop app, you might want to use the new toast system, the code sample on MSDN uses the Windows 8 one. it works on W10 but does not have all the new features (Microsoft released an official NuGet package).
Edit : Since I can't comment, I will post the answer here :
The exception is because you need to provide an applicationId in CreateToastNotifier()
ToastNotificationManager.CreateToastNotifier("MyApplicationId").Show(toast);
It is the name that will be used in the action center to group your toasts (so in general, you put the name of your app). In Windows 8.1 it was needed to register your application Id (I think this was in the sample from the MSDN) but now you can just put the name of your app.
And the GetXml() is only for WinRT. In desktop you need to do like you did with the GetContent().