1

タイトルに間違った名前が付けられている可能性があります。Silverlight BusyIndi​​cator:すべてのChildWindowsより高いZ-インデックス

ChildWindowが開いているときに私が使用しようとしていない限り、 "global"ビジーインジケータは素晴らしいです。

私は私App.xaml.csで静的メソッドを使用して、「グローバル」ビジーインジケータにアクセス:ChildWindowが開いている場合

BusyIndicator b = (BusyIndicator)App.Current.RootVisual; 
if (b != null) 
{ 
    b.BusyContent = busyText; 
    b.IsBusy = true; 
} 

しかし、BusyIndi​​catorは、その背後に常にあります。

私はb.Content = VisualTreeHelper.GetOpenPopups().First()を設定できると思っていましたが、それでもうまくいきませんでした。

誰かが、開いているChildWindowsの上にBusyIndi​​catorを持つためのヒントを持っていますか?

ありがとうございます。

UPDATE(SOLUTION)

デイブS右のトラックに私を送りました。私が望んでいたよりも複雑でしたが、ここで私の解決策です。

まず、私は(ポストサイズ上の理由から、一部を残し)テンプレートのスタイルのすべてをコピーし、ChildWindowのための完全なスタイルをしなければならなかった:

<Style x:Key="MyChildWindowStyle" TargetType="gs:MyChildWindow"> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="gs:MyChildWindow"> 
       <toolkit:BusyIndicator IsBusy="{TemplateBinding IsBusy}" BusyContent="{TemplateBinding BusyContent}" BusyContentTemplate="{StaticResource MyBusyIndicatorDataTemplate}"> 
        <Grid> 
         <ContentPresenter x:Name="ContentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/> 
        </Grid> 
       </toolkit:BusyIndicator> 
</Style> 

その後、私は私の基本クラスを作成しました。コンストラクタがスタイルを設定することに注意してください。 (私はそれが抽象的にするためにしようとした場合にエラーが発生しました。)

public class MyChildWindow : ChildWindow 
{ 
    public static readonly DependencyProperty IsBusyProperty = DependencyProperty.Register("IsBusy", typeof(bool), typeof(MyChildWindow), null); 
    public static readonly DependencyProperty BusyContentProperty = DependencyProperty.Register("BusyContent", typeof(object), typeof(MyChildWindow), null); 

    public bool IsBusy 
    { 
     get { return (bool)GetValue(IsBusyProperty); } 
     set { SetValue(IsBusyProperty, value); } 
    } 

    public object BusyContent 
    { 
     get { return GetValue(BusyContentProperty); } 
     set { SetValue(BusyContentProperty, value); } 
    } 

    public MyChildWindow() 
    { 
     this.Style = Application.Current.Resources["MyChildWindowStyle"] as Style; 
    } 
} 

新しいChildWindowを追加してください、と<コントロールを変更:< GSへChildWindow:MyChildWindow(同じコードビハインドで)。

最後に、静的SetBusyIndi​​cator方法更新:

public static void SetBusyIndicator(string busyText, Uri busyImage) 
{ 
    var op = VisualTreeHelper.GetOpenPopups().Where(o => o.Child is MyChildWindow); 
    if (op.Any()) 
    { 
     var bidc = new MyBusyIndicatorDataContext(busyText, busyImage); 
     foreach (System.Windows.Controls.Primitives.Popup p in op) 
     { 
      var c = p.Child as MyChildWindow; 
      c.BusyContent = bidc; 
      c.IsBusy = true; 
     } 
    } 
    else 
    { 
     BusyIndicator b = Current.RootVisual as BusyIndicator; 
     if (b != null) 
     { 
      b.BusyContent = new MyBusyIndicatorDataContext(busyText, busyImage); 
      b.IsBusy = true; 
     } 
    } 
} 

を私は、これが最も効率的であるわからないんだけど、うまく動作するようには思えません。

答えて

3

ビジースピナーにアプリケーションのルートビジュアルが設定されているため、Z-インデックスをChildWindowよりも高く変更することはできません。あなたの最善の策は、ChildWindowコントロールを拡張し、それにビジースピナーを追加して、ウィンドウを開いたときにルートビジュアルではなくChildWindowにIsBusyを設定することです。

希望に役立ちます。

+0

私の解決策の解決策を含めるように質問が更新されました。あなたの指導に感謝します! – DaleyKD

1

ChildWindowを介してBusyIndi​​catorを使用できるようにChildWindowをサブクラス化する必要はありません。 私は以下のソリューションを使用しています:

1 - すべてのChildWindowコントロールのグローバルContentTemplateを定義します。 IsBusyプロパティをChildWindowのdatacontextの "IsBusy"にバインドします。

<Style TargetType="sdk:ChildWindow"> 
     <Setter Property="ContentTemplate"> 
      <Setter.Value> 
       <DataTemplate> 
        <toolkit:BusyIndicator IsBusy="{Binding IsBusy}"> 
         <ContentPresenter Content="{Binding Content, RelativeSource={RelativeSource TemplatedParent}}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/> 
        </toolkit:BusyIndicator> 
       </DataTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 

2 Silverlightアプリケーションの実行中に準備されたシングルトンクラスを定義します。私はこのためにAppクラスを選んだ。 INotifyPropertyChangedインタフェースを実装して、すべてのIsBusyバインダを自動リフレッシュします。 IsBusyプロパティを実装します。 ShowBusyIndi​​catorメソッドとHideBusyIndi​​catorメソッドを実装します。 ShowBusyIndi​​catorメソッドでは、開いているすべてのChildWindowを繰り返し処理し、DataContextを更新します。

public class App : Application, INotifyPropertyChanged 
{ 
    public static BusyIndicator GlobalBusyIndicator { get; private set; } 

    private bool _isBusy; 
    public bool IsBusy 
    { 
     get 
     { 
      return _isBusy; 
     } 
     set 
     { 
      _isBusy = value; 
      RaisePropertyChanged(new PropertyChangedEventArgs("IsBusy")); 
     } 
    } 

    public static void ShowBusyIndicator() 
    { 
     var popups = VisualTreeHelper.GetOpenPopups(); 
     foreach (var p in popups) 
     { 
      ChildWindow cw = p.Child as ChildWindow; 
      if (cw != null) 
       cw.DataContext = App.Current; 
     } 
     (Current as App).IsBusy = true; 
     GlobalBusyIndicator.IsBusy = true; 
    } 

    public static void HideBusyIndicator() 
    { 
     (Current as App).IsBusy = false; 
     GlobalBusyIndicator.IsBusy = false; 
    } 

    private void Application_Startup(object sender, StartupEventArgs e) 
    { 
     string baseurl = Host.Source.AbsoluteUri; 
     BaseUrl = baseurl.Substring(0, baseurl.IndexOf("ClientBin")); 

     GlobalBusyIndicator = new BusyIndicator(); 
     GlobalBusyIndicator.HorizontalAlignment = HorizontalAlignment.Stretch; 
     GlobalBusyIndicator.VerticalAlignment = VerticalAlignment.Stretch; 
     GlobalBusyIndicator.Content = new Shell(); 

     this.RootVisual = GlobalBusyIndicator; 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    public void RaisePropertyChanged(PropertyChangedEventArgs e) 
    { 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (handler != null) handler(this, e); 
    } 
} 
関連する問題