using System; using System.Collections.Generic; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using AdaptiveCards.Rendering.Uwp; using Monaco; using Monaco.Helpers; using Newtonsoft.Json; // probs don't need these using System.IO; using System.Linq; using System.Runtime.InteropServices.WindowsRuntime; using System.Threading.Tasks; using Windows.Foundation; using Windows.Foundation.Collections; using Windows.UI.Xaml.Controls.Primitives; using Windows.UI.Xaml.Data; using Windows.UI.Xaml.Input; using Windows.UI.Xaml.Media; using Windows.UI.Xaml.Navigation; using Monaco.Editor; using Monaco.Languages; using Newtonsoft.Json.Linq; // The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409 namespace Adaptive_Card_Editor_UWP { /// /// An empty page that can be used on its own or navigated to within a Frame. /// public sealed partial class MainPage : Page { /// /// Create DispatcherTimer for handling input delay logic /// public DispatcherTimer keyTimer = new DispatcherTimer(); /// /// timestamp in ticks (hundred nanoseconds) of last captured KeyUp event /// public long lastKeyUp; /// /// boolean indicating whether input has changed since last tick /// public bool isRendered; /// /// timer interval in ticks (hundred nanoseconds) /// public long interval = 5000000; /// /// list of known entities that contain templated content /// /// /// If the data referenced in the container doesn't exist, the container shouldn't be included in the rendered output /// public List Containers = new List { "ActionSet", "Container", "ColumnSet", "Column", "FactSheet", "Fact", "ImageSet" }; public MainPage() { // set up a window timer for handling the keyup delay TimerSetup(); this.InitializeComponent(); } /// /// Sets up a window timer with a 500ms tick interval and starts the timer /// public void TimerSetup() { // on every timer tick, run TimerTick() keyTimer.Tick += TimerTick; // set the timer interval to half a second keyTimer.Interval = TimeSpan.Parse("00:00:00.05"); // start the timer keyTimer.Start(); } /// /// fires when txtInput sees keyboard input /// private void txtInput_KeyDown(CodeEditor sender, WebKeyEventArgs e) { // last key up event = integer value of current time lastKeyUp = DateTime.Now.Ticks; // user is inputting text, so we're going to rerender isRendered = false; } /// /// fires when txtData sees keyboard input /// private void txtData_KeyDown(CodeEditor sender, WebKeyEventArgs args) { // last key up event = integer value of current time lastKeyUp = DateTime.Now.Ticks; // user is inputting text, so we're going to rerender isRendered = false; } /// /// Fires when the timer ticks /// void TimerTick(object sender, object args) { // if isRendered is true, there have been no changes to input since the last tick if (isRendered) { return; } // otherwise, we done got input, so do the thing else { if (DateTime.Now.Ticks >= lastKeyUp + interval ) { // we done got some input! let's render it. // we don't care what the input is; if it's not valid JSON ignore this keystroke // render the text as a plain textbox TextBlock txtOutput = new TextBlock(); txtOutput.TextWrapping = TextWrapping.Wrap; txtOutput.Padding = new Thickness(10); txtOutput.Text = txtInput.Text; // clear the grid of existing content grdCard.Children.Clear(); // render an adaptive card try { AdaptiveCardRenderer cardRenderer = new AdaptiveCardRenderer(); AdaptiveCardParseResult parsedCard = AdaptiveCard.FromJsonString(txtInput.Text); RenderedAdaptiveCard theCard = cardRenderer.RenderAdaptiveCard(parsedCard.AdaptiveCard); grdCard.Children.Add(theCard.FrameworkElement); } catch (Exception ex) { // this means bad data was ingested by the adaptive card renderer // so just display the exception details txtOutput.Text = ex.ToString(); grdCard.Children.Add(txtOutput); } // render a card using template and data try { string Template = txtInput.Text; string Data = txtData.Text; string Rendered = JsonFromTemplate(Template, Data); // render the card from the rendered template + data AdaptiveCardRenderer cardRenderer = new AdaptiveCardRenderer(); AdaptiveCardParseResult parsedCard = AdaptiveCard.FromJsonString(Rendered); RenderedAdaptiveCard theCard = cardRenderer.RenderAdaptiveCard(parsedCard.AdaptiveCard); grdTemplated.Children.Add(theCard.FrameworkElement); } catch (Exception ex) { // this means bad data was ingested by the adaptive card renderer // so just display the exception details txtOutput.Text = ex.ToString(); grdTemplated.Children.Add(txtOutput); } grdCard.UpdateLayout(); isRendered = true; } else { return; } } } /// /// Creates an adaptive card JSON payload from a template and data model. Follows the official templating language. /// /// JSON adaptive card template /// JSON data model /// JSON string to be ingested by adaptive card renderer public string JsonFromTemplate(string strTemplate, string strData) { string output = ""; // first create JSON objects out of the input JObject Template = JObject.Parse(strTemplate); JObject Data = JObject.Parse(strData); return output; } } }