I'm writing a c# console application that sends toast notifications in VS2017 on a Windows 10 machine. When I run my code and have only defined adaptive text content for my notification it runs correctly and displays the desired text. If I add actions, it no longer displays the adaptive text I defined ("title" and "content" below), nor does it have the option to perform said actions. If I try to add additional visuals such as a logo or picture, they do not appear but the adaptive text is unaffected.
string category = "Notifications";
string title = "New Test Notification!;
string content = "Testing push notifications!";
ToastContent toastContent = new ToastContent()
{
Visual = new ToastVisual()
{
BindingGeneric = new ToastBindingGeneric()
{
Children =
{
new AdaptiveText()
{
Text = title
},
new AdaptiveText()
{
Text = content
}
},
/*AppLogoOverride = new ToastGenericAppLogo()
{
Source = "https://unsplash.it/64?image=883",
HintCrop = ToastGenericAppLogoCrop.Circle
}*/
}
},
/*Actions = new ToastActionsCustom()
{
Buttons =
{
new ToastButton("check", "check")
{
ImageUri = "check.png"
},
new ToastButton("cancel", "cancel")
{
ImageUri = "cancel.png"
}
}
}*/
};
string toastXml = toastContent.GetContent();
XmlDocument doc = new XmlDocument();
doc.LoadXml(toastXml);
var toast = new ToastNotification(doc);
ToastNotificationManager.CreateToastNotifier(category).Show(toast);
Result when above code is run with or without the first block of commented code:
Result when code is run with the second block of commented code:
Related
In my UWP app I'm using two images to test the HintOverLay property with a background image. But the tile does not show the image or or the overlay of the image. I'm using the Maps.xml example of official Notifications Visualizer. Their example works fine on my system. But the following code does not:
Question: What I may be missing and how can we make it work. I've verified that the untitled3.png and untitled4.png exist in the Assets/Apps/ folder. I'm using VS2019 - ver16.6.2 on Windows10 Pro -ver1903?
UPDATE:
Screenshot of Images junk1.png and junk2.png [size: 100x100 pixels]
Screenshot of Solution Explorer:
Code:
.....
.....
TileContent content = new TileContent()
{
Visual = new TileVisual()
{
TileMedium = new TileBinding()
{
Content = new TileBindingContentAdaptive()
{
BackgroundImage = new TileBackgroundImage()
{
Source = "Assets/Apps/junk1.png"
},
PeekImage = new TilePeekImage()
{
Source = "Assets/Apps/junk2.jpg",
HintOverlay = 20
}
}
},
TileWide = new TileBinding()
{
Content = new TileBindingContentAdaptive()
{
BackgroundImage = new TileBackgroundImage()
{
Source = "Assets/Apps/junk1.png"
},
PeekImage = new TilePeekImage()
{
Source = "Assets/Apps/junk2.png",
HintOverlay = 20
}
}
}
}
};
// Create the tile notification
TileNotification notification = new TileNotification(content.GetXml());
TileUpdateManager.CreateTileUpdaterForApplication().EnableNotificationQueue(true);
// Send the notification to the primary tile
TileUpdateManager.CreateTileUpdaterForApplication().Update(notification);
I'm using an Adaptive Card with a multiselect, in the context of Bot created with BotBuilder (Bot Framework):
var card = new AdaptiveCard();
card.Body.Add(new AdaptiveTextBlock()
{
Text = "Q1:xxxxxxxx?",
Size = AdaptiveTextSize.Default,
Weight = AdaptiveTextWeight.Bolder
});
card.Body.Add(new AdaptiveChoiceSetInput()
{
Id = "choiceset1",
Choices = new List<AdaptiveChoice>()
{
new AdaptiveChoice(){
Title="answer1",
Value="answer1"
},
new AdaptiveChoice(){
Title="answer2",
Value="answer2"
},
new AdaptiveChoice(){
Title="answer3",
Value="answer3"
}
},
Style = AdaptiveChoiceInputStyle.Expanded,
IsMultiSelect = true
});
var message = context.MakeMessage();
message.Attachments.Add(new Attachment() { Content = card, ContentType = "application/vnd.microsoft.card.adaptive"});
await context.PostAsync(message);
Now, I would like to know which elements the user has selected.
I would like to know which elements the user has selected.
You can get user's selections from message Value property, the following code snippets work for me, please refer to it.
if (message.Value != null)
{
var user_selections = Newtonsoft.Json.JsonConvert.DeserializeObject<userselections>(message.Value.ToString());
await context.PostAsync($"You selected {user_selections.choiceset1}!");
context.Wait(MessageReceivedAsync);
}
The definition of userselections class:
public class userselections
{
public string choiceset1 { get; set; }
}
Test result:
Update: Code snippet of adding AdaptiveChoiceSetInput and AdaptiveSubmitAction
card.Body.Add(new AdaptiveChoiceSetInput()
{
Id = "choiceset1",
Choices = new List<AdaptiveChoice>()
{
new AdaptiveChoice(){
Title="answer1",
Value="answer1"
},
new AdaptiveChoice(){
Title="answer2",
Value="answer2"
},
new AdaptiveChoice(){
Title="answer3",
Value="answer3"
}
},
Style = AdaptiveChoiceInputStyle.Expanded,
IsMultiSelect = true
});
card.Actions.Add(new AdaptiveSubmitAction()
{
Title = "submit"
});
I am targeting Windows 10, latest OS build. I copy/pasted some stuff from the Microsoft adaptive toast examples--including the paths. Here's my code:
public void CreateToast(ToastViewModel model)
{
ToastContent content = new ToastContent()
{
Launch = "app-defined-string",
Visual = new ToastVisual()
{
BindingGeneric = new ToastBindingGeneric()
{
Children =
{
new AdaptiveText()
{
Text = "Photo Share"
},
new AdaptiveText()
{
Text = "Andrew sent you a picture"
},
new AdaptiveText()
{
Text = "See it in full size!"
},
new AdaptiveImage()
{
Source = "https://unsplash.it/360/180?image=1043"
}
},
HeroImage = new ToastGenericHeroImage()
{
Source = "https://unsplash.it/360/180?image=1043"
},
AppLogoOverride = new ToastGenericAppLogo()
{
Source = "https://unsplash.it/64?image=883",
HintCrop = ToastGenericAppLogoCrop.Circle
}
}
}
};
var toast = new ToastNotification(content.GetXml());
toast.Failed += (o, args) =>
{
var message = args.ErrorCode;
};
ToastNotificationManager.CreateToastNotifier().Show(toast);
}
The toast displays, but the images do not. Anyone have an idea?
EDIT: As #AVK suggested I decided to give it a shot using XML instead; unfortunately I get the same behavior -- toast shows, but no images. Here's my code for that (though admittedly I know even less about XML, so this code could be wrong-er):
var template = ToastTemplateType.ToastImageAndText02;
var xml = ToastNotificationManager.GetTemplateContent(template);
var elements = xml.GetElementsByTagName("text");
var text = xml.CreateTextNode(model.Title);
elements[0].AppendChild(text);
var images = xml.GetElementsByTagName("image");
var srcAttribute = xml.CreateAttribute("src");
srcAttribute.Value = "https://unsplash.it/64?image=883";
images[0].Attributes.SetNamedItem(srcAttribute);
var toast = new ToastNotification(xml);
ToastNotificationManager.CreateToastNotifier().Show(toast);
Http images are only supported in Desktop Bridge apps that have the internet capability in their manifest. Classic Win32 apps do not support http images; you must download the image to your local app data and reference it locally.
This is a Windows 10 bug that causes Toast Notification for applications to not show images.
Run the troubleshooter for Windows apps could fix it.
In my UWP app I am downloading a file and storing it in the location chosen by the user using FolderPicker. When the download has completed, I show a ToastNotification. I am using these two namespaces as shown in the docs.
using Microsoft.QueryStringDotNET; // for receciving arguments
using Microsoft.Toolkit.Uwp.Notifications;
the toast that I send has two buttons, 1) open the file 2) Dismiss.
I want to open the downloaded file when the user taps on the first button.
But from what I understand, toasts can only send string arguments to the application ( Correct me if wrong ). And in order to open a file, StorageFile object is needed ( path of StorageFile won't do ).
So is there any way to actually open the downloaded file from the toast ( using foreground or background activation ) ?
Code to download the file:
private async void DownloadButton_Click(object sender, RoutedEventArgs e)
{
StorageFolder selectedFolder;
try
{
selectedFolder = await ChooseFolderAsync();
}
catch
{
Toast.ShowToast("Something went wrong", ToastRow);
return;
}
Uri downloadLink = new Uri("ValidUri");
StorageFile destinationFile = await selectedFolder.CreateFileAsync(selectedAsset.name, CreationCollisionOption.GenerateUniqueName);
BackgroundDownloader downloader = new BackgroundDownloader();
downloader.SuccessToastNotification = handler.MakeToastWithButtons("Downloaded", selectedAsset.name, "Open", "Dismiss");
// downloader.SuccessToastNotification = handler.MakeToast("Downloaded", nameOfFile, string.Empty, 2);
DownloadOperation download = downloader.CreateDownload(downloadLink, destinationFile);
download.Priority = BackgroundTransferPriority.High;
download.CostPolicy = BackgroundTransferCostPolicy.Always;
var toast = handler.MakeToast("Downloading...", selectedAsset.name, selectedAsset.contentSize, 12);
toast.Group = "downloadStartedTag";
ToastNotificationManager.CreateToastNotifier().Show(toast);
Progress<DownloadOperation> progressCallback = new Progress<DownloadOperation>(handler.DownloadProgress);
try
{
await download.StartAsync().AsTask(cts.Token, progressCallback);
}
catch (Exception ex)
{
var errorCode = BackgroundTransferError.GetStatus(ex.HResult);
toast = handler.MakeToast("Download failed", selectedAsset.name, TextFormatter.CamelToHumanCase(errorCode.ToString()), 12);
toast.Group = "downloadFailedTag";
ToastNotificationManager.CreateToastNotifier().Show(toast);
return;
}
finally
{
ToastNotificationManager.History.Remove("downloadStartedTag");
}
}
Method that creates toast:
public ToastNotification MakeToastWithButtons(string heading, string line1, string button1, string button2)
{
ToastVisual visual = new ToastVisual()
{
BindingGeneric = new ToastBindingGeneric()
{
Children =
{
new AdaptiveText() {Text = heading},
new AdaptiveText() {Text = line1},
}
}
};
ToastActionsCustom actions = new ToastActionsCustom()
{
Buttons =
{
new ToastButton("Open", new QueryString()
{
{ "action", "open" }
//maybe file path can be given here in some argument
}.ToString())
{
ActivationType = ToastActivationType.Foreground
},
new ToastButton("Dismiss", new QueryString()
{
{ "action", "dismiss" }
//more details about the file can be given here
}.ToString())
{
ActivationType = ToastActivationType.Background
}
}
};
ToastContent toastContent = new ToastContent()
{
Visual = visual,
Actions = actions,
// Arguments when the user taps body of toast
Launch = new QueryString()
{
{ "action", "nothing" }
}.ToString()
};
// And create the toast notification
var toast = new ToastNotification(toastContent.GetXml());
toast.ExpirationTime = DateTime.Now.AddDays(2);
toast.Group = "DownloadCompleteGroup";
return toast;
}
One way to do this is to store the destinationFile created by the background download in the FutureAccessList, which will provide you with a token you can add to the payload data of the toast:
// using Windows.Storage.AccessCache;
string token = StorageApplicationPermissions.FutureAccessList.Add(destinationFile);
// add the token to your toast payload
Then when the user clicks the toast, you can redeem the token to get the file back:
var file = await StorageApplicationPermissions.FutureAccessList.GetFileAsync(token);
Now you can do things with the file. Note that the token is good "forever" - as long as the file exists on disk, the token will work after your app restarts or even a reboot.
When you are done with the file (including if the download fails or the user cancels, etc.) you should remove the token from FutureAccessList so that the list doesn't fill up:
StorageApplicationPermissions.FutureAccessList.Remove(token);
This means you likely want to persist the token in your app's settings as well, just in case the user ignores the toast.
I try to show the keyboard chatting telegram using botframework, but the keyboard is not displayed. I tried send keybord like this:
Activity reply = activity.CreateReply(message);
var keyboard =new ReplyKeyboardMarkup
{
Keyboard = new[] { new[] { new KeyboardButton("Text1"), new KeyboardButton("text1") } }
};
reply.ChannelData = keyboard;
await connector.Conversations.ReplyToActivityAsync(reply);
And many other ways. But keyboard does not show up.
What could be the reason? How to make it show up?
You don't need to use ChannelData. Just send the buttons on a HeroCard:
var card = new HeroCard("Some Text");
card.Buttons = new List<CardAction>()
{
new CardAction()
{
Title = "button1",
Type=ActionTypes.ImBack,
Value="button1"
},
new CardAction()
{
Title = "button2",
Type=ActionTypes.ImBack,
Value="button2"
}
};
var reply = activity.CreateReply("");
reply.Attachments = new List<Attachment>();
reply.Attachments.Add(new Attachment()
{
ContentType = HeroCard.ContentType,
Content = card
});
return reply;