0
votes

I have an application which has multiple controls on multiple pages. I'm using the Telerik Winforms controls. One of those pages has a RadGridView in a UserControl, which is on a RadPageViewPage in a RadPageView, which in turn is nested in another RadPageViewPage in another RadPageView. The following code is basically just to handle a Loading spinner that is housed in its own transparent Form. It is always called on its own thread, of course.

private static void RunWaiting(Control c, string text)
{
    wf = new WaitingForm();
    wf.drwbieSpinnerFrame.Text = text;
    wf.ShowInTaskbar = false;
    wf.Left = c.Left + (c.Width / 2); 
    wf.Top = c.Top + (c.Height / 2);
    wf.Width = c.Width;
    wf.Height = c.Height;               
    wf.FormBorderStyle = FormBorderStyle.None;
    wf.ControlBox = false;
    wf.TopMost = true;
    wf.StartPosition = FormStartPosition.Manual;

    Application.Run(wf);
}

Clearly, I want the spinner (WaitForm) to appear over the center of a control on-demand. It's fine if I pass it the main UserControl that houses the RadGridView, and I can also pass it the parent of that control and center on the RadPageViewPage. If I pass this method the RadGridView, the spinner doesn't appear at all, even though the code is called and the attributes of "wf" are still set. Can anyone tell me what I'm missing?

1
I'm not sure why you want to show a forms in another thread, but you can do it this way. - Reza Aghaei
That won't actually work. The spinner form has to be in a separate thread because it needs to run while a long-term operation is going on the main thread. I'm already calling this method from another thread, but it should be centered over the control that is loading data. That's where I'm having trouble. - CDove
In general you don't need to open a form in another thread, the time-consuming task should be in another thread but not your waiting form. Anyway, if you want to open the form from another thread, the link which I shared is the way of opening a form from another thread and surely it works. - Reza Aghaei
I'm already successfully opening the form in another thread. The issue is entirely the actual position of the form. The form itself is transparent and holds a "loading" spinner which needs to continually update while the UI loads data behind it. I tried an async load already and it froze Telerik's RadWaitingBar control. - CDove
I believe you don't need to open the form in another thread, take a look at this post or this one. - Reza Aghaei

1 Answers

0
votes

Unfortunately, the time-consuming task itself is updating the UI and must exist on the UI thread for other reasons, but I was able to put together a solution by using a recursive class that got me the appropriate (x,y) coordinates to display a form in the middle of the control.

private static void RunWaiting(Control c, string text)
        {
            wf = new WaitingForm();
            wf.drwbieSpinnerFrame.Text = text;
            wf.ShowInTaskbar = false;           
            int[] tl = GetTopLefts(c);
            wf.Top = (tl[0] + (c.Height / 2)) - (wf.Height / 2);
            wf.Left = (tl[1] + (c.Width / 2)) - (wf.Width / 2);            
            wf.FormBorderStyle = FormBorderStyle.None;
            wf.ControlBox = false;
            wf.TopMost = true;
            wf.StartPosition = FormStartPosition.Manual;
            IsHolding = true;
            Application.Run(wf);

        }

And the method it calls to get the position data:

private static int[] GetTopLefts(Control c)
        {
            int top, left;
            top = c.Top;
            left = c.Left;
            if (c.Parent != null)
            {
                int[] parentPoint = GetTopLefts(c.Parent);
                top += parentPoint[0];
                left += parentPoint[1];
            }
            return new int[] { top, left };
        }

You could probably get through this just fine by making the final output of GetTopLefts() a Point, but something about this way felt arbitrarily more reliable.