2017-01-10 7 views
0

複数のコントロールを持つアプリケーションがあります。私はTelerik Winformsコントロールを使用しています。これらのページの1つはUserControlRadGridViewを有し、これはRadPageViewRadPageViewPageにあり、次にもう1つのRadPageViewPageを別のRadPageViewに入れ子に入れている。次のコードは、基本的には、独自の透明なフォームに格納されているLoadingスピナーを処理することです。もちろん、それは常に自分のスレッドで呼び出されます。C#Winformsはコントロールの上にフォームを配置し、他のコントロールの上に中央に配置することができます

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); 
} 

は明らかに、私はスピナー(WaitForm)は、オンデマンド制御の中心上に表示します。 RadGridViewが入っているメインのUserControlを渡すといいですし、そのコントロールの親をRadPageViewPageに渡すこともできます。このメソッドをRadGridViewに渡すと、コードが呼び出され、 "wf"の属性が設定されているにもかかわらず、スピンがまったく表示されません。私が何が欠けているか教えてもらえますか?

+0

なぜ私は別のスレッドでフォームを表示したいのか分かりませんが、[この方法で]行うことができます(http://stackoverflow.com/a/41263382/3110834)。 –

+0

実際には動作しません。スピナーフォームは、メインスレッド上で長期的な操作が行われている間に実行する必要があるため、別のスレッドになければなりません。私はすでに別のスレッドからこのメソッドを呼び出していますが、データをロードしているコントロールの中央に配置する必要があります。それが私が困っているところです。 – CDove

+0

一般に、別のスレッドでフォームを開く必要はありません。時間のかかるタスクは別のスレッドで実行する必要があります。とにかく、別のスレッドからフォームを開く場合、私が共有するリンクは別のスレッドからフォームを開く方法であり、確かに動作します。 –

答えて

0

残念なことに、時間のかかるタスク自体はUIを更新しており、他の理由からUIスレッド上に存在する必要がありますが、適切な(x、y)を返す再帰クラスを使用してソリューションをまとめることができました。 )座標を使用して、コントロールの中央にフォームを表示します。

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); 

     } 

そしてそれは、位置データを取得するために呼び出すメソッド:

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 }; 
     } 

おそらくGetTopLefts()Pointの最終的な出力を行うことによって、このを通じてうまく得ることができるが、この方法について何かが任意に感じましたより信頼性の高い。

+1

必要なのは 'c.Parent.PointToScreen(c.Location);'です。なぜあなたは再帰的な方法を使用しますか? –

+0

'int []'の代わりに 'Point'を使うこともできます。 –

+0

'c.Parent.PointToScreen(c.Location)'は、ターミナルサーバー環境でいくつかの問題を引き起こしていました。なぜそれがあったのかわかりませんが、再帰的な方法で生の数学と議論することはできません。それはすばらしいことです。 – CDove

関連する問題