Глобальная загрузка WinRT/Win8(XAML)

Стандартный способ оповещения пользователя о загрузке данных программой из интернета является индикатор из бегающих кубиков сверху экрана(ProgressBar).

 Indeterminat Progress Bar

Чтобы не добавлять на каждую страницу ProgressBar и не передавать состояния загрузки из разных мест на индикатор, можно сделать «глобальную» для всего приложения загрузку. Сам класс GlobalLoading приведен ниже:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
public class GlobalLoading : INotifyPropertyChanged
{
    private ProgressBar _loadingIndicator;
 
    public void Initialize(Frame frame)
    {
        frame.Navigated += OnRootFrameNavigated;
    }
 
    private void OnRootFrameNavigated(object sender, NavigationEventArgs e)
    {
        //после навигации находим корневой грид на странице
        var frameContent = e.Content;
        var page = frameContent as Page;
        if (page == null) return;
 
        var rootGrid = page.Content as Grid;
        if (rootGrid == null) return;
 
        //если уже есть ProgressBar запоминаем его, если нет, то создаем
        if (rootGrid.Children.FirstOrDefault(a => ((a is ProgressBar) && (a as ProgressBar).Name ==         "gl_ind")) != null)
        _loadingIndicator =
rootGrid.Children.First(a => ((a is ProgressBar) && (a as ProgressBar).Name == "gl_ind")) as ProgressBar;
        else
        {
            _loadingIndicator = new ProgressBar
            {
                Name = "gl_ind",
                IsIndeterminate = false,
                HorizontalAlignment = HorizontalAlignment.Stretch,
                VerticalAlignment = VerticalAlignment.Top,
                Margin = new Thickness(0, 10, 0, 0),
                Foreground = new SolidColorBrush(Colors.White),
                BorderBrush = new SolidColorBrush(Colors.White),
                Background = new SolidColorBrush(Colors.Transparent)
            };
 
            rootGrid.Children.Add(_loadingIndicator);
 
            //растягиваем по экрану
            Grid.SetColumnSpan(_loadingIndicator, 99);
            Grid.SetRowSpan(_loadingIndicator, 99);
        }
    }
 
    private static GlobalLoading _instance;
    public static GlobalLoading Instance
    {
        get { return _instance ?? (_instance = new GlobalLoading()); }
    }
 
    private int _loadingCount;
    public bool IsLoading
    {
        get
        {
            return _loadingCount > 0;
        }
        set
        {
            if (value)
            {
                ++_loadingCount;
            }
            else
            {
                --_loadingCount;
            }
 
            NotifyValueChanged();
        }
    }
 
    private void NotifyValueChanged()
    {
        if (_loadingIndicator != null)
        {
            _loadingIndicator.IsIndeterminate = _loadingCount > 0;
        }
    }
 
    public event PropertyChangedEventHandler PropertyChanged;
 
    protected virtual void RaisePropertyChanged(string propertyName)
    {
        var handler = PropertyChanged;
 
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
public class GlobalLoading : INotifyPropertyChanged
{
    private ProgressBar _loadingIndicator;

    public void Initialize(Frame frame)
    {
        frame.Navigated += OnRootFrameNavigated;
    }

    private void OnRootFrameNavigated(object sender, NavigationEventArgs e)
    {
        //после навигации находим корневой грид на странице
        var frameContent = e.Content;
        var page = frameContent as Page;
        if (page == null) return;

        var rootGrid = page.Content as Grid;
        if (rootGrid == null) return;

        //если уже есть ProgressBar запоминаем его, если нет, то создаем
        if (rootGrid.Children.FirstOrDefault(a => ((a is ProgressBar) && (a as ProgressBar).Name ==         "gl_ind")) != null)
        _loadingIndicator =
rootGrid.Children.First(a => ((a is ProgressBar) && (a as ProgressBar).Name == "gl_ind")) as ProgressBar;
        else
        {
            _loadingIndicator = new ProgressBar
            {
                Name = "gl_ind",
                IsIndeterminate = false,
                HorizontalAlignment = HorizontalAlignment.Stretch,
                VerticalAlignment = VerticalAlignment.Top,
                Margin = new Thickness(0, 10, 0, 0),
                Foreground = new SolidColorBrush(Colors.White),
                BorderBrush = new SolidColorBrush(Colors.White),
                Background = new SolidColorBrush(Colors.Transparent)
            };

            rootGrid.Children.Add(_loadingIndicator);

            //растягиваем по экрану
            Grid.SetColumnSpan(_loadingIndicator, 99);
            Grid.SetRowSpan(_loadingIndicator, 99);
        }
    }

    private static GlobalLoading _instance;
    public static GlobalLoading Instance
    {
        get { return _instance ?? (_instance = new GlobalLoading()); }
    }

    private int _loadingCount;
    public bool IsLoading
    {
        get
        {
            return _loadingCount > 0;
        }
        set
        {
            if (value)
            {
                ++_loadingCount;
            }
            else
            {
                --_loadingCount;
            }

            NotifyValueChanged();
        }
    }

    private void NotifyValueChanged()
    {
        if (_loadingIndicator != null)
        {
            _loadingIndicator.IsIndeterminate = _loadingCount > 0;
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void RaisePropertyChanged(string propertyName)
    {
        var handler = PropertyChanged;

        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Для для работы с ним необходимо сделать инициализацию в файле App.xaml.cs после каждого создания Frame:

1
2
rootFrame = new Frame();
GlobalLoading.Instance.Initialize(rootFrame);
rootFrame = new Frame();
GlobalLoading.Instance.Initialize(rootFrame);

Далее перед каждым началом запроса на сервер нужно вызвать:

1
GlobalLoading.Instance.IsLoading = true;
GlobalLoading.Instance.IsLoading = true;

А после получения ответа(включая ошибки):

1
GlobalLoading.Instance.IsLoading = false;
GlobalLoading.Instance.IsLoading = false;

Пример