如何在UWP / UAP上实现模板化

时间:2016-04-29 12:09:18

标签: c# .net windows-10 template-engine windows-10-universal

我需要根据UWP / UAP项目中的某些模型生成HTML - 完全用C#编写。

问题是没有预先存在的模板引擎(我真的不想从头开始编写)与平台兼容。我找了几个最受欢迎的替代品,没有一个可以开箱即用。

对于我所面临的这个实质性问题,您建议的解决方案是什么?我想过移植一个可用的开源库,但我不确定它是否值得付出努力。

我对解决问题的答案或模板引擎(对UAP没有真正起作用)的建议不感兴趣,只是在解决Windows 10通用应用程序模板问题的最简单方法中。

1 个答案:

答案 0 :(得分:2)

如果您正在使用HTML/JavaScript进行开发,则可以在WinJS中使用内置HTML库进行模板化。此外,Microsoft为AngularReactKnockout创建了一些adapters,以便在UWP个应用中使用它们。

通常大多数JavaScript代码都可以正常工作,在嵌入iframe或外部脚本时,唯一需要考虑的是security limitations。要绕过此类限制,您应该更新已使用库的逻辑或使用execUnsafeLocalFunction方法手动强制执行。

MSApp.execUnsafeLocalFunction(function() {
    var body = document.getElementsByTagName('body')[0];
    body.innerHTML = '<div style="color:' + textColor + '">example</div>';
});

== 更新:

对于C#,有两种选择:

  1. 继续寻找图书馆,或者自己推动图书馆进行转换,或者
  2. 构建一个围绕webview控件的包装器,它将使用已有的库为您完成。
  3. 在第二种情况下,应该很容易: 1)您应该使用您在JavaScript中选择的任何库来实现从JSON到HTML(带模板)的转换器,它应该可用于从外部上下文(全局函数或对象)进行调用。这样的函数应该作为JSON字符串接收数据并返回一个字符串(例如来自innerHTML)。 2)使用标准技术和InvokeScriptAsync / ScriptNotify事件,WebView控件在C#和JS环境之间传输数据。您实际上不需要在页面内显示WebView。只需将它用作JS执行的环境,即可访问相应库所需的DOM。

    以下是WinJS的代码示例: 带有WinJS库的 HTML / JS。 template.html文件。全球js-function:

    function convertFromJSON2HTML(jsonString, templateHTML) {
        var templateEl = document.createElement("div");
        templateEl.innerHTML = templateHTML;
    
        var jsonData = JSON.parse(jsonString);
    
        if (WinJS != undefined) {
            var template = new WinJS.Binding.Template(templateEl);
    
            //promise
            template.render(jsonData).done(function(output) {
                window.external.notify(output.innerHTML);
            });
        } else {
               // catch error
        }
    }
    

    C#代码

    public async Task<string> GenerateTemplate(string jsonData, string template)
    {
        var webView = new WebView();
        webView.Source = new Uri("ms-appx-web:///HTML/template.html");
    
        webView.DOMContentLoaded += async (o, e) =>
        {
            await webView.InvokeScriptAsync("convertFromJSON2HTML", new string[] { jsonData, template });
        };            
    
        string output = "";
    
        // Simple trick to convert event result to async result
        TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
        webView.ScriptNotify += (o, e) =>
        {
            output = e.Value;
            tcs.SetResult(true);
        };
        await tcs.Task;
        return output;
    }
    

    用法。我在这里使用的是WinJS风格的模板:

    var result = await GenerateTemplate("{\"x\":\"test\"}","<p data-win-bind='textContent:x'></p>");
    resultBox.Text = result;
    

    为了简化通信,我建议使用AddAllowedWebObject方法在两个环境之间传递WinRT对象,而不仅仅是文本。