【问题标题】:Silverlight BusyIndicator : Higher Z-Index than all ChildWindowsSilverlight BusyIndi​​cator:比所有 ChildWindows 都高的 Z-Index
【发布时间】:2012-03-07 00:58:12
【问题描述】:

可能标题用错了。

我有一个很好用的“全局”忙碌指示器,只要我在 ChildWindow 打开时不尝试使用它。

我在 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 有任何提示吗?

提前致谢。

更新(解决方案)

Dave S 让我走上了正轨。它比我希望的要复杂,但这是我的解决方案。

首先,我必须为 ChildWindow 制作一个完整的样式,复制所有的 Template 样式(由于后期大小的原因而遗漏了一些):

<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,并将

最后,更新静态 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;
        }
    }
}

我不确定这是最有效的方法,但它似乎工作得很好。

【问题讨论】:

    标签: silverlight silverlight-toolkit childwindow busyindicator


    【解决方案1】:

    您不必将 ChildWindow 子类化即可在 ChildWindows 上使用 BusyIndi​​cator。 我正在使用以下解决方案:

    1-为所有 ChildWindow 控件定义全局 ContentTemplate。将 IsBusy 属性绑定到 ChildWindow 的数据上下文的“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 并更新它们的 DataContexts。

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

    【讨论】:

      【解决方案2】:

      当您将应用程序根视觉设置为繁忙的微调器时,您将无法更改 Z-Index,因此它高于 ChildWindow。最好的办法是扩展 ChildWindow 控件并在其中添加一个繁忙的微调器,然后在打开窗口时在 ChildWindow 而不是根视觉对象上设置 IsBusy。

      希望对您有所帮助。

      【讨论】:

      • 我更新了问题以包含我的工作解决方案。感谢您的指导!
      猜你喜欢
      • 2011-03-01
      • 2012-04-11
      • 2011-03-27
      • 2011-08-17
      • 2011-03-15
      • 2013-09-29
      • 2012-01-07
      • 2012-05-06
      • 2012-04-30
      相关资源
      最近更新 更多