окно ожидания
#38321453
Ссылка:
Ссылка на сообщение:
Ссылка с названием темы:
|
|
|
Для решения задачи в стартовом посте я использую стандартный способ через BusyIndicator.
Класс:
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 индикатора:
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>
Использование в разметке окна:
1. 2. 3.
<myctrls:BusyIndicator x:Name="BISLAFR" BusyContent="Loading data..." IsBusy="{Binding}">
//здесь другие контролы, которые блокируются, пока происходит ожидание
<myctrls:BusyIndicator>
Использование либо через биндинг в xaml, либо в коде через BISLAFR.IsBusy=true/false
|
|