Home

LINQPad 5 controls bug

I noticed a small bug when prototyping a small solution utilizing the built-in controls. I built a LINQPad solution to showcase the issue, but it won't allow me to attach LINQPad queries here, so I'll paste the code in instead.

Use the code below to demonstrate the issue.

var input = new TextArea() { Rows = 1 }.Dump();

// Set Styles
input.Styles["position"] = "fixed";
input.Styles["bottom"] = "0";
input.Styles["left"] = "2px";
input.Styles["width"] = "100.35%";

// Set Events
input.HtmlElement.AttachEventHandler("onkeyup", (sender, args) =>
{
    input.Text.Dump();
});

// Uncomment to Break Styles/Events
/*Thread.Sleep(1000);
new Literal(@"<script></script>").Dump();*/

Run the query with the lines commented out to see the desired results. Then repeat the process with them uncommented.

The issue is when you customize a control by adding styles and attaching event handlers and then, later on, execute a script tag it will break styling and the events will no longer fire.

In this case, even an empty script tag will break the styles and events.

One thing I found difficult with the control also is to determine what key was pressed (for special keys). For example, with the given control I had no way to determine when the enter key was pressed. I had to add custom javascript (via a script literal tag) to track the key and write it to an attribute on the element that the c# event would have to grab. Maybe a feature request, or maybe I'm missing something?

Something like this is how I did it:

input.HtmlElement.AttachEventHandler("onkeyup", (sender, args) =>
{
    var elem = sender as LINQPad.Controls.Core.HtmlElement;

    var key = elem.GetAttribute("key");
    if (key == "13")
    {
        // Do enter key things
    }
});

// Javascript
new Literal(
$@"<script>
    var txt = document.getElementById('{input.HtmlElement.ID}');

    // Handle the 'keydown' event
    txt.addEventListener('keydown', function(e) {{
        txt.setAttribute('key', (window.event) ? e.which : e.keyCode);
    }});
</script>").Dump();

Comments

  • I want to add I'm probably using LINQPad beyond its intent. If you give people a screwdriver eventually someone will try to use it as a hammer. ;) I do want to add working through this project has opened my eyes to how impressive this 'simple' application has been. I want to personally thank you for this gem. <3

  • Thanks for your support!

    You're probably running into a limitation in the IE11 engine and/or its integration via the WebBrowser control. I'm hoping MS will update this soon to use the new Edge/Chromium engine. I'll take another look soon to see if there's a workaround, and whether there's a mechanism for sending the keypress info across.

  • edited February 2020

    Thank you for your response. I was going to suggest looking into using some sort of Chromium engine or maybe using Electron (or some other derivative) for your UI.

    I haven't used the WebBrowser control before and wasn't sure if the Styles or AttachEvents methods were part of the control or some logic that you added to the control objects.

    Are the LINQPad controls directly objects accessible via the web browser controls, or are they wrappers you've written around WebBrowser controls and/or HTML elements?

    I'm using LINQPad as an intranet chat client, that disguises messages as c# code. haha. It is capable of sending files, also will automatically add audio/video elements if the files are audio or video. So I'm heavily leveraging the UI portion of things. Using drag/drop for file transfers..etc

    Let me know if I can help at all with testing.

  • I've discovered what's causing the problem that you're experiencing and will release a fix shortly. I might also make it easier to define and execute scripts, and make it possible to emit them into the HTML head rather than inline.

    In terms of accessing details of the keypress event, I might expose another method for this. The AttachEventHandler method doesn't really make it possible to get data back from the event.

    Unfortunately, you can't get direct access to the WebBrowser and its DOM, because it runs in the LINQPad host process, and so everything has to be remoted across.

  • Thank you so much for looking in to this. Am I correct in assuming the same bug exists in LINQPad 6?

  • I've just uploaded a LINQPad 6 beta with the bugfix and also some new features for working with scripts (see Help | What's New). Let me know how you get along.

    If this works, I'll backport the bugfix to LINQPad 5 (although the new scripting features won't make it).

  • Joe, I just downloaded the latest LINQPad 6 beta and re-ran my example above. While it didn't break the styling/events which is good, it didn't execute the script. So for example change the commented out lines to this:

    Thread.Sleep(1000);
    new Literal(@"<script>alert('Test')</script>").Dump();
    

    In the old version, it would break the styling/events, but it would still execute the script. In the new version, it no longer breaks the styling/events but now it no longer fires the alert.

    We use LINQPad 5 premium at our company and haven't bitten the bullet to switch to 6 yet, I forgot how much nicer it is to use the premium features. ;)

    Also, super low priority, but would it be possible when executing either javascript console.log() or console.error() to somehow see this? Would speed up development instead of having to alert values. I'm sure there aren't many leveraging the UI like this, so don't spend any unnecessary time on this.

  • Try now.

    Regarding a logging method, the good news is that this was very easy to add. Here's how to call it:

    external.log('test')
    
  • edited February 2020

    Joe, You are amazing! Thank you so much, everything seems to be in order, and I love the external.log option. Just make sure that little tidbit makes its way into the documentation somehow. Let me know if it would be possible to port the fix to LINQPad 5. Thanks again, and keep up the good work!

    Also if you do ever decide to toy around with reworking the LINQPad UI I stumbled upon Electron.NET (https://github.com/ElectronNET/Electron.NET) and it seems to be promising (I'm writing my LINQPad prototype in it). Maybe worth taking a quick look at. Visual Studio Code uses Electron and it might enable you to more easily make LINQPad cross-platform.

  • A LINQPad 5 beta with the fix will be released soon. It will also include the external.log method, but no support for the Util.HtmlHead methods.

  • The LINQPad 5 beta with the fix (5.42) is now available.

  • Thank you Joe. It is appreciated.

Sign In or Register to comment.