Home

Easy way to create clickable non-text objects?

edited January 2022

I'm trying to create a script to help with sorting through images and choosing from different sets. The images would be displayed in the set and by clicking on the image, it would be chosen.

I've made some dynamic interfaces in the past using hyperlinqs and buttons (among other controls) but it all was either text links or browser buttons. I know I could make other controls clickable (through the Click event) but the content has to be controls as well. I could generate the raw html myself but that defeats the purpose. I want the images (through Util.Image()) to be directly clickable.

Ideally Hyperlinqs could use objects for the "content" or add something similar to Util.WithStyle(). Like a Util.Clickable() with overloads similar to a Hyperlinq. It would just make the thing perform some action when clicked. Could make using Hyperlinqs more consistent with many of the Util methods.

class ImageSet
{
    private List<string> files;
    public ImageSet(IEnumerable<string> files) => this.files = files.ToList();

    object ToDump()
    {
        var container = new DumpContainer();
        UpdateContainer();
        return container;

        void UpdateContainer()
        {
            container.Content = files.Count switch
            {
                0 => "" as object,
                1 => files.Select(f => Util.VerticalRun(
                    f,
                    Util.Image(f, Util.ScaleMode.ResizeTo(200)),
                )).Single(),
                _ => Util.VerticalRun(
                    Util.Clickable(() => ChooseNone(), "Choose None"), // <-- interchangeable with Hyperlinq
                    Util.HorizontalRun(true, files.Select(f =>
                        Util.VerticalRun(
                            Util.Clickable(f, f), // <-- synonymous with new Hyperlinq(f, f)
                            Util.Clickable( // <--- something like this
                                () => ChooseImage(f),
                                Util.Image(f, Util.ScaleMode.ResizeTo(200)),
                            )
                        )
                    ))
                ),
        }
        void ChooseImage(string path)
        {
            files.RemoveAll(f => f != path);
            UpdateContainer();
        }
        void ChooseNone()
        {
            files.Clear();
            UpdateContainer();
        }
    }
}

Is there something I could use to accomplish this? Could this be added?

Comments

  • I was able to simulate it using a LINQPad.Controls.Control to host a DumpContainer that would hold the content. Though, when it's rendered, it does some interesting things.

    static class UtilEx
    {
        public static object Clickable(string uriOrPath, string text) => new Hyperlinq(uriOrPath, text);
        public static object Clickable(Action action, object content)
        {
            var clickable = new LINQPad.Controls.Control(new DumpContainer(content));
            clickable.Click += (_, _) => action();
            return clickable;
        }
    }
    
  • I feel your pain. Try the 7.2.6 beta - there's now a LINQPad.Controls.Image class, with the same image source and scaling flexibility as Util.Image:
    https://www.linqpad.net/LINQPad7.aspx#beta

Sign In or Register to comment.