powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / WPF, Silverlight [игнор отключен] [закрыт для гостей] / окно ожидания
32 сообщений из 32, показаны все 2 страниц
окно ожидания
    #38320118
netivan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ситуация простая: нужно вызвать диалоговое окно, пока что-то выполянется в другом потоке. Причем сделать это так, чтобы было очень удобно использовать. С backgroundWorker что-то решения мне не понравились, но нашел вот такой способ:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
using (SplashWindow ....("load data...") //открывает форму, где просто надпись
			{
				var task = new Task(() =>
					{
						for (int i = 0; i < 1000; i++)
						{
							res = Math.Sin(45.6);
							Thread.Sleep(50);
						}
					});

				var nestedFrame = new DispatcherFrame();
				task.ContinueWith(_ => nestedFrame.Continue = false);
				task.Start();
				Dispatcher.PushFrame(nestedFrame);
				task.Wait();
				task.Dispose();

				MessageBox.Show(res.ToString(CultureInfo.InvariantCulture));
			}


Если честно напрягает использование Dispatcher.PushFrame, могут тут быть подводные камни? Спасибо за подсказку)
...
Рейтинг: 0 / 0
окно ожидания
    #38320291
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
netivanЕсли честно напрягает использование Dispatcher.PushFrame, могут тут быть подводные камни? Спасибо за подсказку)Идея использовать Task - правильная. У меня была раньше реализация через PushFrame, не понравилась. В итоге понравилась такая постановка задачи:
Код: c#
1.
2.
3.
4.
5.
6.
    Task.Factory
        .StartNew(() => { ... })
        .ContinueWith(() => { ... })
        .ContinueWith(() => { ... })
        .LockUi(); // <= Расширяющий метод для Task.
        .ContinueWith(() => { ... })


Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
    public static class UiTaskHelper
    {
        public static Task<T> LockUi<T>(this Task<T> task)
        {
            return UiExecutionLocker.I.SetTask(task); // о ужас, синглетон :-) 
        }

        public static Task LockUi(this Task task)
        {
            return UiExecutionLocker.I.SetTask(task);
        }
    }


Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
    public class UiExecutionLocker
    {
        public Task<T> SetTask<T>(Task<T> task)
        {
            AddRef(); // инкремент счётчика ссылок + отображение диалога
                          // форма отображается через BeginInvoke + ShowDialog.
            return task.ContinueWithSync(t =>
            {
                Release(); // декремент счётчика ссылок + закрытие диалога
                return t.Result;
            });
        }

        public Task SetTask(Task task)
        {
            AddRef();
            return task.ContinueWithSync(t =>
            {
                Release();
                t.ThrowIfException();
            });
        }
    }
...
Рейтинг: 0 / 0
окно ожидания
    #38320375
netivan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей К,

не поверишь, именно от тебя ждал ответа. Чем не понравился frame? Можешь пример использования вашего велосипеда скинутЬ?
...
Рейтинг: 0 / 0
окно ожидания
    #38320409
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
netivanне поверишь, именно от тебя ждал ответа.Неожиданно. :-)
netivanЧем не понравился frame?Я наверное по другому сформулирую. Через frame решение вполне рабочее, но с предлагаемым решением работать удобнее , если асинхронности базируются на тасках. Боюсь, я точно сейчас не смогу сформулировать недостатки. Нужно вспоминать, писать примеры. :-)

Тут вообще возможны два способа индикации выполняемой фоновой задачи:
1. Обсуждаемый случай - диалогом. Применяется, если нужно блокировать UI на время выполнения фоновой операции.
2. Индикация без блокирования UI. Можно сделать какой-нибудь анимацией в статусбаре главной формы, или ещё как.

Одно из преимуществ - для обоих случаев применяется одинаковый подход.
netivanМожешь пример использования вашего велосипеда скинутЬ?Первый фрагмент кода и есть пример использования. Если там что-то непонятно - уточните вопрос, я поясню.
...
Рейтинг: 0 / 0
окно ожидания
    #38320416
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ещё желательно сделать отображение диалога с задержкой (где-то в 0.5 секунды), чтобы для коротких тасков диалог не мелькал на экране. Но это уже следующий шаг. :-)
...
Рейтинг: 0 / 0
окно ожидания
    #38320419
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей К, гавнокод. Нужно декларативно через mvvm.
...
Рейтинг: 0 / 0
окно ожидания
    #38320426
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Можно и так сформулировать - при использовании тасков в PushFrame нет необходимости. :-)
...
Рейтинг: 0 / 0
окно ожидания
    #38320434
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
МСУгавнокод.Ну можно же подобрать другое слово. У нас же вроде мараторий на фекальные формулировки. :-)
МСУНужно декларативно через mvvm.Конечно. Но это уже следующий этап. Аспнетчикам не понять.
...
Рейтинг: 0 / 0
окно ожидания
    #38320441
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей КНу можно же подобрать другое слово.
Ок. "кодкоторыйнихеранекоррелируетскачествомиэргономикой" :)

Алексей ККонечно.
Всё должно само замлиться и декларативно подтягиваться :)
...
Рейтинг: 0 / 0
окно ожидания
    #38320445
netivan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей К,

можно про AddRef и Release подробнее.
...
Рейтинг: 0 / 0
окно ожидания
    #38320452
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
netivanАлексей К, можно про AddRef и Release подробнее.
Ну а что тут подробнее, утечка на утечке и утечкой погоняет
...
Рейтинг: 0 / 0
окно ожидания
    #38320463
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
netivanАлексей К,

можно про AddRef и Release подробнее.
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
        RefCounter IsActiveRefCounter = new RefCounter(); 
            
        void AddRef() 
        {   
            if (IsActiveRefCounter.IsNoReference) 
            { 
                  // показываем диалог, только асинхронно, через Dispatcher.BeginInvoke
            } 
  
            IsActiveRefCounter.AddRef(); 
        } 
  
        void Release() 
        {  
            IsActiveRefCounter.Release(); 
  
            if (IsActiveRefCounter.IsNoReference) 
            { 
                 // закрываем диалог
            } 
        }


Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
    public class RefCounter 
    { 
        int Count; 
  
        public void AddRef() 
        { 
            Count++; 
        } 
  
        public void Release() 
        { 
            if (IsNoReference) 
                throw new InvalidOperationException("IsNoReference == true"); 
  
            Count--; 
        } 
  
        public bool IsNoReference 
        { 
            get { return Count == 0; } 
        } 
    } 
...
Рейтинг: 0 / 0
окно ожидания
    #38320467
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
МСУnetivanАлексей К, можно про AddRef и Release подробнее.
Ну а что тут подробнее, утечка на утечке и утечкой погоняет Тебя SeVa что ли укусил?
...
Рейтинг: 0 / 0
окно ожидания
    #38320472
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
netivanАлексей К,

можно про AddRef и Release подробнее.Это надо на случай, когда одновременно выполняются несколько тасков. Мы же не будем для них показывать несколько диалогов "Подождите". :-)
...
Рейтинг: 0 / 0
окно ожидания
    #38320482
netivan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей КnetivanАлексей К,

можно про AddRef и Release подробнее.Это надо на случай, когда одновременно выполняются несколько тасков. Мы же не будем для них показывать несколько диалогов "Подождите". :-) ага, только ща понял. Спасибо! Только у меня все же пока что 1 Таск планируется. Сейчас попробую с вашим примером)
...
Рейтинг: 0 / 0
окно ожидания
    #38320498
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей К, сколько же опасного кода :)

Окно ожидания в вебе с блокировкой UI:

Код: javascript
1.
$.blockUI({ message: '<h4><img src="busy.gif" />Лячкайте... Выполняется что-то.</h4>' }); });



Делов-то .
...
Рейтинг: 0 / 0
окно ожидания
    #38320544
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
МСУАлексей К, сколько же опасного кода :)

Окно ожидания в вебе с блокировкой UI:

Код: javascript
1.
$.blockUI({ message: '<h4><img src="busy.gif" />Лячкайте... Выполняется что-то.</h4>' }); });



Делов-то . Вообще-то мы обсуждаем реализацию. Прикладной код проще некуда. Давай я его ещё раз повторю, для верности. :-)
Код: c#
1.
2.
3.
4.
5.
    Task.Factory
        .StartNew(() => { ... })
        .ContinueWith(() => { ... })
        .ContinueWith(() => { ... })
        .LockUi(); // <= оно самое
...
Рейтинг: 0 / 0
окно ожидания
    #38320554
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
netivanАлексей Кпропущено...
Это надо на случай, когда одновременно выполняются несколько тасков. Мы же не будем для них показывать несколько диалогов "Подождите". :-) ага, только ща понял. Спасибо! Только у меня все же пока что 1 Таск планируется. Сейчас попробую с вашим примером)Ещё обрати внимание на ContinueWithSync. Это ContinueWith через шедулер, привязанный к контексту синхронизации главного UI-потока.
...
Рейтинг: 0 / 0
окно ожидания
    #38320558
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей КВообще-то мы обсуждаем реализацию. Прикладной код проще некуда. Давай я его ещё раз повторю, для верности. :-)
Всё-равно, пока еще не знаю, но что-то мне не нравится в этом коде :)
...
Рейтинг: 0 / 0
окно ожидания
    #38320561
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
МСУАлексей КВообще-то мы обсуждаем реализацию. Прикладной код проще некуда. Давай я его ещё раз повторю, для верности. :-)
Всё-равно, пока еще не знаю, но что-то мне не нравится в этом коде :)Не бесит, уже хорошо. :-)
...
Рейтинг: 0 / 0
окно ожидания
    #38320566
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей КНе бесит, уже хорошо. :-)
Ну, не бесит, конечно, но суховато как-то... Десктоп он такой :)
...
Рейтинг: 0 / 0
окно ожидания
    #38320591
netivan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей КМСУпропущено...

Всё-равно, пока еще не знаю, но что-то мне не нравится в этом коде :)Не бесит, уже хорошо. :-)
ну так. Может еще обернуть в RunTaskAsynkWithMsgBox()
...
Рейтинг: 0 / 0
окно ожидания
    #38320621
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
netivanАлексей Кпропущено...
Не бесит, уже хорошо. :-)
ну так. Может еще обернуть в RunTaskAsynkWithMsgBox()Мне в виде расширяющего метода для таска нравится больше. Тем более, после закрытия диалога "подождите" может быть продолжение, вроде:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
    Task.Factory
        .StartNew(() => { ... })
        .ContinueWith(() => { return Task.Factory.FromAsync(...); })
        .Unwrap();
        .ContinueWith(() => { ... })
        .LockUi(); // подождите
        .ContinueWithSync(() => // про синхронизацию писал выше.
        {
              // окошко надо показать после закрытия диалога "подождите"
              MessageBox.Show("Тру ла ла");
        })
        .ContinueWith(() => { ... }) // ещё что-то асинхронное
        .LockUi(); // ещё раз подождите
        .ContinueWithSync(() =>
        {
              MessageBox.Show("Ну теперь точно готово");
        })
        .LogExceptions(); // запись ошибок в лог, к теме отношения не имеет, но добавил навсякий :-)
...
Рейтинг: 0 / 0
окно ожидания
    #38320639
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ужас ёпт
...
Рейтинг: 0 / 0
окно ожидания
    #38320658
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
netivanну так. Может еще обернуть в RunTaskAsynkWithMsgBox()Ну и конечно же, .LockUi() отображает дефолтный диалог, описанный как синглетон. Если для таска нужен специальный диалог, то создаём UiExecutionLocker явно. Получается что-то вроде того, что ты предлагаешь:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
var task = Task.Factory.StartNew(() => { ... });

var locker = new UiExecutionLocker
{
    Content = new MyUserControlOrЧтоТоЕщё() // содержимое окна
}; 

locker
    .SetTask(task)
    .ContinueWith(t => { ... }) // какое-то продолжение после закрытия окна, если надо
    .LogExceptions(); // не забываем обрабатывать ошибки. :-)
...
Рейтинг: 0 / 0
окно ожидания
    #38320666
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
МСУУжас ёптЭто тебе не странички на аспнете клепать. Тут всё серьёзно. Я чуть мозг себе не повредил, когда это придумывал.
...
Рейтинг: 0 / 0
окно ожидания
    #38320679
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей КЯ чуть мозг себе не повредил, когда это придумывал.
А если уволишься? Ведь всё РЖД встанет раком!
...
Рейтинг: 0 / 0
окно ожидания
    #38320728
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
МСУАлексей КЯ чуть мозг себе не повредил, когда это придумывал.
А если уволишься? Ведь всё РЖД встанет раком! Ну не всё. Но кое что может. :-)
...
Рейтинг: 0 / 0
окно ожидания
    #38320774
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей КМСУпропущено...

А если уволишься? Ведь всё РЖД встанет раком! Ну не всё. Но кое что может. :-)Не эксплуатация а доработка конечно. Во всяком случае хочется в это верить.
...
Рейтинг: 0 / 0
окно ожидания
    #38321068
unknownfromrus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей К,

А почему в тасках для записи в лог не указал параметр OnlyOnFaulted для логирования? Или ты пишешь все подряд?
...
Рейтинг: 0 / 0
окно ожидания
    #38321098
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
unknownfromrusАлексей К,

А почему в тасках для записи в лог не указал параметр OnlyOnFaulted для логирования? Или ты пишешь все подряд?Там внутри LogExceptions() соответствующий ContinueWith стоит.
...
Рейтинг: 0 / 0
окно ожидания
    #38321453
Lost_Stranger
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Для решения задачи в стартовом посте я использую стандартный способ через BusyIndicator.
Класс:

Код: c#
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.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
using System;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Shapes;
    using System.Windows.Threading;

    /// <summary>
    /// A control to provide a visual indicator when an application is busy.
    /// </summary>
    [TemplateVisualState(Name = VisualStates.StateIdle, GroupName = VisualStates.GroupBusyStatus)]
    [TemplateVisualState(Name = VisualStates.StateBusy, GroupName = VisualStates.GroupBusyStatus)]
    [TemplateVisualState(Name = VisualStates.StateVisible, GroupName = VisualStates.GroupVisibility)]
    [TemplateVisualState(Name = VisualStates.StateHidden, GroupName = VisualStates.GroupVisibility)]
    [StyleTypedProperty(Property = "OverlayStyle", StyleTargetType = typeof(Rectangle))]
    [StyleTypedProperty(Property = "ProgressBarStyle", StyleTargetType = typeof(ProgressBar))]
    public class BusyIndicator : ContentControl
    {
        /// <summary>
        /// Gets or sets a value indicating whether the BusyContent is visible.
        /// </summary>
        protected bool IsContentVisible { get; set; }

        /// <summary>
        /// Timer used to delay the initial display and avoid flickering.
        /// </summary>
        private DispatcherTimer _displayAfterTimer;

        /// <summary>
        /// Instantiates a new instance of the BusyIndicator control.
        /// </summary>
        public BusyIndicator()
        {
            DefaultStyleKey = typeof(BusyIndicator);
            _displayAfterTimer = new DispatcherTimer();
            _displayAfterTimer.Tick += new EventHandler(DisplayAfterTimerElapsed);
        }

        /// <summary>
        /// Overrides the OnApplyTemplate method.
        /// </summary>
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            ChangeVisualState(false);
        }

        /// <summary>
        /// Handler for the DisplayAfterTimer.
        /// </summary>
        /// <param name="sender">Event sender.</param>
        /// <param name="e">Event arguments.</param>
        private void DisplayAfterTimerElapsed(object sender, EventArgs e)
        {
            _displayAfterTimer.Stop();
            IsContentVisible = true;
            ChangeVisualState(true);
        }

        /// <summary>
        /// Changes the control's visual state(s).
        /// </summary>
        /// <param name="useTransitions">True if state transitions should be used.</param>
        protected virtual void ChangeVisualState(bool useTransitions)
        {
            VisualStateManager.GoToState(this, IsBusy ? VisualStates.StateBusy : VisualStates.StateIdle, useTransitions);
            VisualStateManager.GoToState(this, IsContentVisible ? VisualStates.StateVisible : VisualStates.StateHidden, useTransitions);
        }

        /// <summary>
        /// Gets or sets a value indicating whether the busy indicator should show.
        /// </summary>
        public bool IsBusy
        {
            get { return (bool)GetValue(IsBusyProperty); }
            set { SetValue(IsBusyProperty, value); }
        }

        /// <summary>
        /// Identifies the IsBusy dependency property.
        /// </summary>
        public static readonly DependencyProperty IsBusyProperty = DependencyProperty.Register(
            "IsBusy",
            typeof(bool),
            typeof(BusyIndicator),
            new PropertyMetadata(false, new PropertyChangedCallback(OnIsBusyChanged)));

        /// <summary>
        /// IsBusyProperty property changed handler.
        /// </summary>
        /// <param name="d">BusyIndicator that changed its IsBusy.</param>
        /// <param name="e">Event arguments.</param>
        private static void OnIsBusyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((BusyIndicator)d).OnIsBusyChanged(e);
        }

        /// <summary>
        /// IsBusyProperty property changed handler.
        /// </summary>
        /// <param name="e">Event arguments.</param>
        protected virtual void OnIsBusyChanged(DependencyPropertyChangedEventArgs e)
        {
            if (IsBusy)
            {
                if (DisplayAfter.Equals(TimeSpan.Zero))
                {
                    // Go visible now
                    IsContentVisible = true;
                }
                else
                {
                    // Set a timer to go visible
                    _displayAfterTimer.Interval = DisplayAfter;
                    _displayAfterTimer.Start();
                }
            }
            else
            {
                // No longer visible
                _displayAfterTimer.Stop();
                IsContentVisible = false;
            }
            ChangeVisualState(true);
        }

        /// <summary>
        /// Gets or sets a value indicating the busy content to display to the user.
        /// </summary>
        public object BusyContent
        {
            get { return (object)GetValue(BusyContentProperty); }
            set { SetValue(BusyContentProperty, value); }
        }

        /// <summary>
        /// Identifies the BusyContent dependency property.
        /// </summary>
        public static readonly DependencyProperty BusyContentProperty = DependencyProperty.Register(
            "BusyContent",
            typeof(object),
            typeof(BusyIndicator),
            new PropertyMetadata(null));

        /// <summary>
        /// Gets or sets a value indicating the template to use for displaying the busy content to the user.
        /// </summary>
        public DataTemplate BusyContentTemplate
        {
            get { return (DataTemplate)GetValue(BusyContentTemplateProperty); }
            set { SetValue(BusyContentTemplateProperty, value); }
        }

        /// <summary>
        /// Identifies the BusyTemplate dependency property.
        /// </summary>
        public static readonly DependencyProperty BusyContentTemplateProperty = DependencyProperty.Register(
            "BusyContentTemplate",
            typeof(DataTemplate),
            typeof(BusyIndicator),
            new PropertyMetadata(null));

        /// <summary>
        /// Gets or sets a value indicating how long to delay before displaying the busy content.
        /// </summary>
        public TimeSpan DisplayAfter
        {
            get { return (TimeSpan)GetValue(DisplayAfterProperty); }
            set { SetValue(DisplayAfterProperty, value); }
        }

        /// <summary>
        /// Identifies the DisplayAfter dependency property.
        /// </summary>
        public static readonly DependencyProperty DisplayAfterProperty = DependencyProperty.Register(
            "DisplayAfter",
            typeof(TimeSpan),
            typeof(BusyIndicator),
            new PropertyMetadata(TimeSpan.FromSeconds(0.1)));

        /// <summary>
        /// Gets or sets a value indicating the style to use for the overlay.
        /// </summary>
        public Style OverlayStyle
        {
            get { return (Style)GetValue(OverlayStyleProperty); }
            set { SetValue(OverlayStyleProperty, value); }
        }

        /// <summary>
        /// Identifies the OverlayStyle dependency property.
        /// </summary>
        public static readonly DependencyProperty OverlayStyleProperty = DependencyProperty.Register(
            "OverlayStyle",
            typeof(Style),
            typeof(BusyIndicator),
            new PropertyMetadata(null));

        /// <summary>
        /// Gets or sets a value indicating the style to use for the progress bar.
        /// </summary>
        public Style ProgressBarStyle
        {
            get { return (Style)GetValue(ProgressBarStyleProperty); }
            set { SetValue(ProgressBarStyleProperty, value); }
        }

        /// <summary>
        /// Identifies the ProgressBarStyle dependency property.
        /// </summary>
        public static readonly DependencyProperty ProgressBarStyleProperty = DependencyProperty.Register(
            "ProgressBarStyle",
            typeof(Style),
            typeof(BusyIndicator),
            new PropertyMetadata(null));
    }



XAML индикатора:

Код: xml
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.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:sys="clr-namespace:System;assembly=mscorlib"
    xmlns:appControls="clr-namespace:sba_seti_skuke.Controls">

    <Style TargetType="appControls:BusyIndicator" x:Key="busyIndicatorDefaultStyle">
        <Setter Property="BusyContent" Value="Please wait..."/>
        <Setter Property="IsTabStop" Value="False"/>
        <Setter Property="OverlayStyle">
            <Setter.Value>
                <Style TargetType="Rectangle">
                    <Setter Property="Fill" Value="White"/>
                    <Setter Property="Opacity" Value="0.5"/>
                </Style>
            </Setter.Value>
        </Setter>
        <Setter Property="ProgressBarStyle">
            <Setter.Value>
                <Style TargetType="ProgressBar">
                    <Setter Property="IsIndeterminate" Value="True"/>
                    <Setter Property="Height" Value="15"/>
                    <Setter Property="Margin" Value="8,0,8,8"/>
                </Style>
            </Setter.Value>
        </Setter>
        <Setter Property="DisplayAfter" Value="00:00:00.1"/>
        <Setter Property="HorizontalAlignment" Value="Stretch"/>
        <Setter Property="VerticalAlignment" Value="Stretch"/>
        <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
        <Setter Property="VerticalContentAlignment" Value="Stretch"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="appControls:BusyIndicator">
                    <Grid>
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="VisibilityStates">
                                <VisualState x:Name="Hidden">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.001" Storyboard.TargetName="busycontent" Storyboard.TargetProperty="(UIElement.Visibility)">
                                            <DiscreteObjectKeyFrame KeyTime="00:00:00">
                                                <DiscreteObjectKeyFrame.Value>
                                                    <Visibility>Collapsed</Visibility>
                                                </DiscreteObjectKeyFrame.Value>
                                            </DiscreteObjectKeyFrame>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.001" Storyboard.TargetName="overlay" Storyboard.TargetProperty="(UIElement.Visibility)">
                                            <DiscreteObjectKeyFrame KeyTime="00:00:00">
                                                <DiscreteObjectKeyFrame.Value>
                                                    <Visibility>Collapsed</Visibility>
                                                </DiscreteObjectKeyFrame.Value>
                                            </DiscreteObjectKeyFrame>
                                        </ObjectAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="Visible">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.001" Storyboard.TargetName="busycontent" Storyboard.TargetProperty="(UIElement.Visibility)">
                                            <DiscreteObjectKeyFrame KeyTime="00:00:00">
                                                <DiscreteObjectKeyFrame.Value>
                                                    <Visibility>Visible</Visibility>
                                                </DiscreteObjectKeyFrame.Value>
                                            </DiscreteObjectKeyFrame>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.001" Storyboard.TargetName="overlay" Storyboard.TargetProperty="(UIElement.Visibility)">
                                            <DiscreteObjectKeyFrame KeyTime="00:00:00">
                                                <DiscreteObjectKeyFrame.Value>
                                                    <Visibility>Visible</Visibility>
                                                </DiscreteObjectKeyFrame.Value>
                                            </DiscreteObjectKeyFrame>
                                        </ObjectAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                            <VisualStateGroup x:Name="BusyStatusStates">
                                <VisualState x:Name="Idle">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.001" Storyboard.TargetName="content" Storyboard.TargetProperty="(Control.IsEnabled)">
                                            <DiscreteObjectKeyFrame KeyTime="00:00:00">
                                                <DiscreteObjectKeyFrame.Value>
                                                    <sys:Boolean>True</sys:Boolean>
                                                </DiscreteObjectKeyFrame.Value>
                                            </DiscreteObjectKeyFrame>
                                        </ObjectAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="Busy">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.001" Storyboard.TargetName="content" Storyboard.TargetProperty="(Control.IsEnabled)">
                                            <DiscreteObjectKeyFrame KeyTime="00:00:00">
                                                <DiscreteObjectKeyFrame.Value>
                                                    <sys:Boolean>False</sys:Boolean>
                                                </DiscreteObjectKeyFrame.Value>
                                            </DiscreteObjectKeyFrame>
                                        </ObjectAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                        <ContentControl
                            x:Name="content"
                            Content="{TemplateBinding Content}"
                            ContentTemplate="{TemplateBinding ContentTemplate}"
                            HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
                            VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
                        <Rectangle
                            x:Name="overlay"
                            Style="{TemplateBinding OverlayStyle}"/>
                        <ContentPresenter
                            x:Name="busycontent">
                            <Grid
                                HorizontalAlignment="Center"
                                VerticalAlignment="Center">
                                <Border
                                    Background="White"
                                    BorderThickness="1"
                                    CornerRadius="2">
                                    <Border.BorderBrush>
                                        <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                                            <GradientStop Color="#FFA3AEB9" Offset="0"/>
                                            <GradientStop Color="#FF8399A9" Offset="0.375"/>
                                            <GradientStop Color="#FF718597" Offset="0.375"/>
                                            <GradientStop Color="#FF617584" Offset="1"/>
                                        </LinearGradientBrush>
                                    </Border.BorderBrush>
                                    <Border
                                        CornerRadius="1.5"
                                        Margin="1">
                                        <Border.Background>
                                            <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                                                <GradientStop Color="#FFF6F8F9" Offset="0.02"/>
                                                <GradientStop Color="#FFB8B8B8" Offset="0.996"/>
                                            </LinearGradientBrush>
                                        </Border.Background>
                                        <Grid MinWidth="150">
                                            <Grid.RowDefinitions>
                                                <RowDefinition/>
                                                <RowDefinition Height="Auto"/>
                                            </Grid.RowDefinitions>
                                            <ContentPresenter
                                                Content="{TemplateBinding BusyContent}"
                                                ContentTemplate="{TemplateBinding BusyContentTemplate}"
                                                Margin="8"/>
                                            <ProgressBar
                                                Grid.Row="1"
                                                Style="{TemplateBinding ProgressBarStyle}"/>
                                        </Grid>
                                    </Border>
                                </Border>
                            </Grid>
                        </ContentPresenter>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>



Использование в разметке окна:

Код: xml
1.
2.
3.
<myctrls:BusyIndicator x:Name="BISLAFR" BusyContent="Loading data..." IsBusy="{Binding}">
 //здесь другие контролы, которые блокируются, пока происходит ожидание
<myctrls:BusyIndicator>



Использование либо через биндинг в xaml, либо в коде через BISLAFR.IsBusy=true/false
...
Рейтинг: 0 / 0
32 сообщений из 32, показаны все 2 страниц
Форумы / WPF, Silverlight [игнор отключен] [закрыт для гостей] / окно ожидания
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]