Home
Options

Issue with refreshing Dump Containers, possibly

edited September 2023

Hi,
I'm a bigtime fan of Linqpad and use it pretty much daily.
I've been diving into using Linqpad.Controls a lot and I wrote some custom stuff, a lot of which was 'just cuz'. It's not really all that useful, per se, but anyway...
I wrote something that essentially dumps a list of supplied Funcs and prints the output with a Hyperlink in each box that allows you to refresh the contents of the box (kinda like hitting refresh button in the Visual Studio debugger watch window).
I can share the whole custom controls script I have but the one that is acting slightly odd is this:

public class EvalList<T> : Control, IEnumerable<T>
{
    public IEnumerator<T> GetEnumerator()
    {
        return _list.Select(x => (T)Invoke(x) ).GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

    private readonly string _label = string.Empty;
    private readonly List<Func<T>> _list;

    public EvalList(string label, IEnumerable<Func<T>> data) : this(data)
    {
        _label = label;
    }
    public EvalList(IEnumerable<Func<T>> data)
    {
        _list = data.ToList();
    }
    object? Invoke(Func<T> x) => Util.Try(x, e => default(T));
    public object ToDump()
    {
        var tuples = _list.Select(x =>
        {
            var dc = new DumpContainer(Invoke(x)); 
            return new { dc, hl = new Hyperlink("↺", _ => dc.Content = Invoke(x) ) }; 
        });
        var returnValue = tuples.Select(x => Util.HorizontalRun(true, x.dc, x.hl));
        var vr = new StackPanel(false,
            new Button("Rerun all", _ => { foreach (var v in tuples.Zip(_list)) { v.First.dc.UpdateContent(Invoke(v.Second)); v.First.dc.Refresh(); } }),
            new DumpContainer(returnValue)
        );
        return !string.IsNullOrEmpty(_label) ? new FieldSet(_label, vr) : vr;
    }
}

Code to test the control:

void Main()
{
    var r = new Random();

    var a = from x in Enumerable.Range(1, 5) select new Func<string>(() => r.Next(x * 1000).ToString());
    new EvalList<string>("a bunch of times", a).Dump("EvalList");
}

Here's what happens:

demo

I tried running the script in VS debugger and when it gets to the Rerun all button lambda, I see the values are being produced by the Func, and the contents of the Dump Container show up as being changed but they don't refresh in the window.

As you can see in the demo, clicking each individually works fine. Clicking rerun all doesn't. Any idea why? What am I doing wrong?

Comments

  • Options

    You need to add .ToArray() here:

        public object ToDump()
        {
            var tuples = _list.Select (x =>
            {
                var dc = new DumpContainer (Invoke (x));
                return new { dc, hl = new Hyperlink ("↺", _ => dc.Content = Invoke (x)) };
            }).ToArray();
    

    otherwise you'll end up with different objects when re-enumerated.

    Also, EvalList doesn't need to inherit from Control, because you've defined a ToDump method.

  • Options

    :(facepalm

    Thank you. I knew it had to be something silly.

Sign In or Register to comment.