Использовать Blockly внутри WPF WebBrowser

Можно ли использовать библиотеки Blockly google javascript внутри веб-браузера WPF?

В частности, Blockly требует нескольких js-скриптов. Как мы можем ссылаться на библиотеки js?

Ответ 1

Короткий ответ

Вы можете использовать все блокирующие функции, включая инструменты пользовательского интерфейса и функции API, из элемента управления WPF WebBrowser. Для этого вам необходимо:

  • Создайте содержимое HTML, которое содержит теги script, ссылающиеся на Blocky js, или методы, которые вы хотите вызывать из С#, и требуемое содержимое HTML и XML в соответствии с вашими требованиями (например, набор инструментов и рабочее пространство). Вы можете загружать набор инструментов и рабочее пространство динамически во время выполнения.
  • Загрузка содержимого в элемент управления WebBrowser с помощью Navigate или NavigateToString
  • Если вам нужно вызвать скрипт, используйте метод InvokeScript элемента управления WebBrowser.

Кроме того, чтобы иметь возможность использовать Blocky, вы должны заставить WebBrowser использовать режим последней версии документа без режима совместимости и показывать современный контент.


Пример

Этот пример показывает:

  • Как вы можете загружать набор инструментов динамически
  • Как вы можете загружать рабочее пространство динамически
  • Как вы можете вызывать блочные методы API, используя методы javascript. В примере вы можете видеть прокси-методы showCode и runCode, которые не зависят от wprkspace и будут работать с любым рабочим пространством. Вы можете вызывать методы JavaScript из С#.

Вы можете использовать любой из блочных демонстраций, например. Я создал пример, который показывает как использование Blocky API, так и Blocky UI Tools. Этот пример основан на примере Generation Javascript, который показывает, как использовать Blocky API для генерации javascript из рабочей области Blocky.

enter image description here

Скачать

Вы можете клонировать или скачать рабочий пример с:

Создание примера шаг за шагом

В примере содержится простой HTML файл, в заголовок которого добавлены необходимые файлы JavaScript. Также он содержит два прокси-метода, которые мы создали для вызова из С#.

Также пример содержит два XML файла. Включено для рабочей области "Блочный" и одно для панели инструментов.

Примечание: создание этих файлов не является обязательным, и вы можете динамически создавать рабочее пространство или набор инструментов во время выполнения. Это просто для того, чтобы показать, что вы можете загрузить рабочее пространство и набор инструментов во время выполнения, и они не должны быть статичными.

1) Создать приложение WPF

Создайте проект WPF и назовите его WpfAppllicatin1.

2) Создать файл blockyWorkspace.xml

Создайте файл blockyWorkspace.xml, используя содержимое ниже. Этот файл будет использоваться для создания блочного рабочего пространства.

<xml>
<block type="controls_if" inline="false" x="20" y="20">
    <mutation else="1"></mutation>
    <value name="IF0">
    <block type="logic_compare" inline="true">
        <field name="OP">EQ</field>
        <value name="A">
        <block type="math_arithmetic" inline="true">
            <field name="OP">ADD</field>
            <value name="A">
            <block type="math_number">
                <field name="NUM">6</field>
            </block>
            </value>
            <value name="B">
            <block type="math_number">
                <field name="NUM">7</field>
            </block>
            </value>
        </block>
        </value>
        <value name="B">
        <block type="math_number">
            <field name="NUM">13</field>
        </block>
        </value>
    </block>
    </value>
    <statement name="DO0">
    <block type="text_print" inline="false">
        <value name="TEXT">
        <block type="text">
            <field name="TEXT">Don't panic</field>
        </block>
        </value>
    </block>
    </statement>
    <statement name="ELSE">
    <block type="text_print" inline="false">
        <value name="TEXT">
        <block type="text">
            <field name="TEXT">Panic</field>
        </block>
        </value>
    </block>
    </statement>
</block>
</xml>

3) Создать файл blockyToolbox.xml

Создайте файл blockyToolbox.xml, используя содержимое ниже. Этот файл будет использоваться для создания панели инструментов Blocky.

<xml>
    <block type="controls_if"></block>
    <block type="logic_compare"></block>
    <block type="controls_repeat_ext"></block>
    <block type="math_number"></block>
    <block type="math_arithmetic"></block>
    <block type="text"></block>
    <block type="text_print"></block>
</xml>

4) Создать файл blockyHTML.html

Создайте файл blockyHTML.html, используя содержимое ниже. Этот файл просто содержит ссылку на скриптовые блоки, а также на наши методы javascript, которые будут вызываться из нашего приложения с использованием кода С#:

<html>
<head>
  <meta http-equiv="X-UA-Compatible" content="IE=10" />
  <script src="https://blockly-demo.appspot.com/static/blockly_compressed.js"></script>
  <script src="https://blockly-demo.appspot.com/static/blocks_compressed.js"></script>
  <script src="https://blockly-demo.appspot.com/static/javascript_compressed.js"></script>
  <script src="https://blockly-demo.appspot.com/static/msg/js/en.js"></script>
</head>
<body>
    <div id="host" style="height: 480px; width: 600px;"></div>
    <script>
        var workspace;
        function init(toolboxXML, workspaceXML) {
            workspace = Blockly.inject('host',
            { media: '../../media/', toolbox: toolboxXML });
            var wx = Blockly.Xml.textToDom(workspaceXML)
            Blockly.Xml.domToWorkspace(wx, workspace);
        }
        function showCode() {
            Blockly.JavaScript.INFINITE_LOOP_TRAP = null;
            var code = Blockly.JavaScript.workspaceToCode(workspace);
            return code;
        }
        function runCode() {
            window.LoopTrap = 1000;
            Blockly.JavaScript.INFINITE_LOOP_TRAP =
                'if (--window.LoopTrap == 0) throw "Infinite loop.";\n';
            var code = Blockly.JavaScript.workspaceToCode(workspace);
            Blockly.JavaScript.INFINITE_LOOP_TRAP = null;
            try { eval(code); } catch (e) { alert(e); }
        }
    </script>
</body>
</html>

5) Написать код С#

Поместите элемент управления WebBrowser, назовите его browser и обработайте его событие LoadCompleted. Также поместите два элемента управления Button в окна и назовите их showCodeButton и runCodeButton и обработайте их события Click следующим образом:

public MainWindow()
{
    InitializeComponent();
    showCodeButton.IsEnabled = false;
    runCodeButton.IsEnabled = false;
    browser.NavigateToString(System.IO.File.ReadAllText(@"d:\blockyHTML.html"));
}
private void browser_LoadCompleted(object sender, NavigationEventArgs e)
{
    showCodeButton.IsEnabled = true;
    runCodeButton.IsEnabled = true;
    var toolboxXML = System.IO.File.ReadAllText(@"d:\blockyToolbox.xml");
    var workspaceXML = System.IO.File.ReadAllText(@"d:\blockyWorkspace.xml");
    //Initialize blocky using toolbox and workspace
    browser.InvokeScript("init", new object[] { toolboxXML, workspaceXML });
}
private void showCodeButton_Click(object sender, RoutedEventArgs e)
{
    var result = browser.InvokeScript("showCode", new object[] { });
    MessageBox.Show(result.ToString());
}
private void runCodeButton_Click(object sender, RoutedEventArgs e)
{
    browser.InvokeScript("runCode", new object[] { });
}

6) Запустить приложение

Когда вы запустите приложение, после того, как кнопки будут активированы, нажмите на первую кнопку, а затем вы можете получить результат метода showCode, который использует блочный API для генерации кода JavaScript из блочной рабочей области.

Также вы можете запустить код, который вы создали, используя blocky, нажав на вторую кнопку.

enter image description here enter image description here

Ответ 2

Только что обновил пример @reza-aghaei для использования элемента управления UWP WebView в .NET 4.8

https://github.com/rosesby/Blockly-.NET-Example-With-UWP-WebView

он работает хорошо, но в отличие от обычного элемента управления webBrowser, он не поддерживает отображение предупреждений JavaScript, как обсуждено здесь: функция JavaScript() не работает в приложении UWP