1

おそらく、タイトルの言い回しが間違っています。

チャイルドウィンドウが開いているときに使用しようとしない限り、うまく機能する「グローバル」ビジーインジケーターがあります。

App.xaml.csで静的メソッドを使用して、「グローバル」ビジーインジケーターにアクセスします。

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

ただし、ChildWindowが開いている場合、BusyIndi​​catorは常にその背後にあります。

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

開いているChildWindowsの上にBusyIndi​​catorを配置するためのヒントはありますか?

前もって感謝します。

更新(解決策)

デイブ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を追加し、<controls:ChildWindowを<gs: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;
        }
    }
}

これが最も効率的かどうかはわかりませんが、うまく機能しているようです。

4

2 に答える 2

3

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

それが役立つことを願っています。

于 2012-02-15T17:40:16.170 に答える
1

ChildWindows で 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 メソッドで、開いているすべての ChildWindows を反復処理し、それらの 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);
    }
}
于 2012-09-12T07:50:15.627 に答える