рдпрд╣ рд▓реЗрдЦ
рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рд╕рдВрдЪрд╛рд▓рди рдФрд░ рдЕрдзрд┐рдХ рдХреЗ рд▓рд┐рдП рд╕реНрд╡рдЪрд╛рд▓рд┐рдд BusyIndicator рд▓реЗрдЦ рдХрд╛ рдПрдХ рдирд┐рд░рдВрддрд░рддрд╛ рд╣реИред
attached property
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ
attached property
рд╣рдореЗрдВ XAML рдореЗрдВ рд▓рд┐рдЦрдирд╛ рд╣реЛрдЧрд╛:
<BusyIndicator AsyncIndicator.Attached="true" > <ListBox ItemsSource="{Binding DataList, IsAsync=true}" ...> ... </ListBox> <BusyIndicator>
рдореЗрд░реЗ рд▓рд┐рдП - рдЖрдк рдХрдо рдХрд▓реНрдкрдирд╛ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ!
рдЖрдЗрдП рдорд╛рдирдХ рдкреНрд░реЛрдЯреЛрдЯрд╛рдЗрдк
attached property
рд╕рд╛рде рд╢реБрд░реВ рдХрд░реЗрдВ:
public static class AsyncIndicator { static AsyncIndicator() { } public static readonly DependencyProperty AttachedProperty = DependencyProperty.RegisterAttached("Attached", typeof (bool), typeof (ContentControl), new FrameworkPropertyMetadata(false, AttachedChanged)); public static Boolean GetAttached(UIElement element) { return (Boolean) element.GetValue(AttachedProperty); } public static void SetAttached(UIElement element, Boolean value) { element.SetValue(AttachedProperty, value); } private static void AttachedChanged(DependencyObject busyIndicator, DependencyPropertyChangedEventArgs e) { } }
рджрд┐рд▓рдЪрд╕реНрдк рд╣реИ, GetAttached
рдФрд░ SetAttached
рд╕реИрджреНрдзрд╛рдВрддрд┐рдХ рд░реВрдк рд╕реЗ рдЕрдирд╛рд╡рд╢реНрдпрдХ рд╣реИрдВ рдФрд░ рдХрднреА рднреА рд╣рдорд╛рд░реА рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореЗрдВ рдирд╣реАрдВ рдХрд╣реЗ рдЬрд╛рддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЙрдирдХреЗ рдмрд┐рдирд╛ attached property
рдЙрдкрд▓рдмреНрдз рдирд╣реАрдВ рд╣реЛрдЧреАредрд╣рдо
AttachedChanged
рдЗрд╡реЗрдВрдЯ рд╡рд┐рдзрд┐ рдореЗрдВ рд░реБрдЪрд┐ рд░рдЦрддреЗ рд╣реИрдВред рд╕рд╛рдорд╛рдиреНрдп рд╡рд┐рдЪрд╛рд░ рдпрд╣ рд╣реИ: рд╣рдо
BusyIndicator
рдХреА рд╕рд╛рдордЧреНрд░реА рдФрд░
BusyIndicator
(рдЕрдзрд┐рдХ рд╕рдЯреАрдХ рд░реВрдк рд╕реЗ,
dependency property
BusyIndicator
) рдХреА рддрд▓рд╛рд╢ рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рдпрджрд┐ рдРрд╕реА рдХреЛрдИ рдкреНрд░реЙрдкрд░реНрдЯреА рдкрд╛рдИ рдЬрд╛рддреА рд╣реИ, рддреЛ рд╣рдо рдЙрд╕ рдкрд▓ рдХреЛ рд░реЛрдХрддреЗ рд╣реИрдВ рдЬрдм рдкреНрд░реЙрдкрд░реНрдЯреА рдмрджрд▓реА рдЬрд╛рддреА рд╣реИред рдпрджрд┐ рдЗрд╕рдХрд╛ рдорд╛рди
null
- рд╕рдВрдХреЗрддрдХ рдХреЛ рдЪрд╛рд▓реВ рдХрд░реЗрдВ, рдЕрдиреНрдпрдерд╛ - рдЗрд╕реЗ рдмрдВрдж рдХрд░реЗрдВред
рдереЛрдбрд╝реА рд╕реА рдХрдард┐рдирд╛рдИ рддреБрд░рдВрдд рдЙрддреНрдкрдиреНрди рд╣реЛ рдЬрд╛рддреА рд╣реИ:
AttachedChanged
рдХреЙрд▓рд┐рдВрдЧ рдХреЗ рд╕рдордп,
BusyIndicator
рдХреА рд╕рд╛рдордЧреНрд░реА рдЕрднреА рддрдХ рд╕реНрдерд╛рдкрд┐рдд рдирд╣реАрдВ рд╣реБрдИ рд╣реИ, рдЬреЛ рдмрд┐рд▓реНрдХреБрд▓ рднреА рдЖрд╢реНрдЪрд░реНрдпрдЬрдирдХ рдирд╣реАрдВ рд╣реИред
ContentControl
рдХреА рддрд░рд╣ рдПрдХ рдорд╛рдирдХ рдИрд╡реЗрдВрдЯ рдирд╣реАрдВ рдорд┐рд▓ рд░рд╣рд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдЗрд╕рдХреЗ рдЪрд╛рд░реЛрдВ рдУрд░ рдЬрд╛рдирд╛ рдерд╛:
private static void AttachedChanged(DependencyObject busyIndicator, DependencyPropertyChangedEventArgs e) { SetPropertyChangedCallback(ContentControl.ContentProperty, busyIndicator, ContentChangedCallback); } private static void SetPropertyChangedCallback(DependencyProperty dp, DependencyObject d, PropertyChangedCallback callback, bool reset = false) { if (dp == null || d == null) return; var typ = d.GetType(); var metadata = dp.GetMetadata(typ); var oldValue = metadata.SetPropValue("Sealed", false); metadata.PropertyChangedCallback -= callback; if (!reset) metadata.PropertyChangedCallback += callback; metadata.SetPropValue("Sealed", oldValue); } private static void ContentChangedCallback(DependencyObject busyIndicator, DependencyPropertyChangedEventArgs e) { if (!(bool) busyIndicator.GetValue(AttachedProperty)) return; SetBusyIndicator(e.OldValue as DependencyObject, null); SetBusyIndicator(e.NewValue as DependencyObject, busyIndicator); }
рдореИрдВ рдЗрд╕ рдХреЛрдб рдкрд░ рдереЛрдбрд╝реА рдЯрд┐рдкреНрдкрдгреА рдХрд░реВрдВрдЧрд╛ред
SetPropertyChangedCallback
рд╡рд┐рдзрд┐
dependency property ContentProperty
рдХрд╛ рдореЗрдЯрд╛рдбреЗрдЯрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЗрд╕ рд╕рдВрдкрддреНрддрд┐ рдХреЗ рдореВрд▓реНрдп рдХреЛ рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдИрд╡реЗрдВрдЯ рд╣реИрдВрдбрд▓рд░ рдЬреЛрдбрд╝рддрд╛ рд╣реИ (рдпрд╛ рд╣рдЯрд╛рддрд╛ рд╣реИ)ред
рдпрд╣рд╛рдВ рдПрдХ рдЫреЛрдЯреА рд╕реА рд╣реИрдХ рд╣реИ: рддрдереНрдп рдпрд╣ рд╣реИ рдХрд┐ рдЖрдк рдХреЗрд╡рд▓ рдЖрд░рдВрдн рдХреЗ рдмрд╛рдж рдореЗрдЯрд╛рдбреЗрдЯрд╛ рдирд╣реАрдВ рдмрджрд▓ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреЛ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдЕрдкрд╡рд╛рдж рдореЗрдВ рдХрд╣рд╛ рдЧрдпрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдБрдХрд┐,
PropertyMetadata.cs
рдореЙрдбреНрдпреВрд▓ рдХреЗ рд╕реНрд░реЛрдд рдХреЛрдб рдХреЗ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рд╕реЗ рдкрддрд╛ рдЪрд▓рд╛ рд╣реИ рдХрд┐ рдЗрд╕ рдЖрд░рдВрднреАрдХрд░рдг рдХрд╛ рдПрдХ рд╕рдВрдХреЗрдд
internal
Sealed
рд╕рдВрдкрддреНрддрд┐ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЛрдб рдХреЛ рдЕрд╡реНрдпрд╡рд╕реНрдерд┐рдд рдирд╣реАрдВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдореИрдВ
SetPropValu
рд╡рд┐рдзрд┐ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХрд╛ рд╣рд╡рд╛рд▓рд╛ рдирд╣реАрдВ рджреЗрддрд╛, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдХреЛрдИ рднреА рдкреНрд░рддрд┐рдмрд┐рдВрдм рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╡рд╕реНрддреБ рдХреА рд╕рдВрдкрддреНрддрд┐ рдореЗрдВ рдмрджрд▓рд╛рд╡ рдирд╣реАрдВ рд▓рд┐рдЦ рдкрд╛рдПрдЧрд╛ред
рдпрджрд┐ WPF рдХреЗ рдХрд┐рд╕реА рд╡реНрдпрдХреНрддрд┐ рдиреЗ рдЖрдкрдХреЛ рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рдФрд░ рдЕрдзрд┐рдХ рд╕реБрдВрджрд░ рддрд░реАрдХреЗ рд╕реЗ рд╣рд▓ рдХрд░рдиреЗ рдХрд╛ рддрд░реАрдХрд╛ рдмрддрд╛рдпрд╛ рд╣реИ - рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ, plz рдореЗрдВ рд▓рд┐рдЦреЗрдВредрдЕрдм,
ContentChangedCallback
рд╡рд┐рдзрд┐ рдХреЛ рд╣рдорд╛рд░реЗ
BusyIndicator
рдкрд░
BusyIndicator
'a' рдореЗрдВ рдирдИ рд╕рд╛рдордЧреНрд░реА рдХреА рд╕реНрдерд╛рдкрдирд╛ рдХреЗ рд▓рд┐рдП рдмреБрд▓рд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдЗрд╕ рд╡рд┐рдзрд┐ рдХреА рдкрд╣рд▓реА рдкрдВрдХреНрддрд┐ рдмрд╣реБрдд рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ - рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕ рдкрджреНрдзрддрд┐ рдХреЛ рд╕рднреА
BusyIndicator
рд▓рд┐рдП рдмреБрд▓рд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛, рди рдХрд┐ рдХреЗрд╡рд▓ рдПрдХ рдЬрд┐рд╕рдХреЗ рд▓рд┐рдП рд╣рдордиреЗ
AsyncIndicator.Attached="true"
рдкреНрд░реЙрдкрд░реНрдЯреА рд╕реЗрдЯ рдХреА рд╣реИред рдЗрд╕рд▓рд┐рдП, рд╣рдо рдЬрд╛рдВрдЪрддреЗ рд╣реИрдВ рдХрд┐ рдЗрд╕ рд╕рдВрдкрддреНрддрд┐ рдХрд╛ рдореВрд▓реНрдп
true
рдмрд░рд╛рдмрд░
true
ред
рдЗрд╕ рд╡рд┐рдзрд┐ рдХреА рджреВрд╕рд░реА рдкрдВрдХреНрддрд┐ рдкрд┐рдЫрд▓реЗ рд╕рд╛рдордЧреНрд░реА рдХреЗ рд▓рд┐рдП рдЖрдЗрдЯрдо рд╕реНрд░реЛрдд рдкрд░рд┐рд╡рд░реНрддрди рдИрд╡реЗрдВрдЯ рдХреЛ рдЕрдХреНрд╖рдо рдХрд░ рджреЗрддреА рд╣реИ, рдФрд░ рддреАрд╕рд░рд╛, рдЗрд╕рдХреЗ рд╡рд┐рдкрд░реАрдд, рдИрд╡реЗрдВрдЯ рдХреЛ рдирдИ рд╕рд╛рдордЧреНрд░реА рдореЗрдВ рдЬреЛрдбрд╝рддрд╛ рд╣реИред
SetBusyIndicator
рд╡рд┐рдзрд┐ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ:
private static readonly DependencyProperty _busyIndicatorProperty = DependencyProperty.RegisterAttached("%BusyIndicatorProperty%", typeof (ContentControl), typeof (DependencyObject)); private static void SetBusyIndicator(DependencyObject contentObject, DependencyObject busyIndicator) { if (contentObject != null) { SetPropertyChangedCallback(GetItemsSourceValue(contentObject), contentObject, ItemsSourceChangedCallback, busyIndicator == null); contentObject.SetValue(_busyIndicatorProperty, busyIndicator); } UpdateBusyIndicator(busyIndicator, contentObject); } private static object GetItemsSourceValue(DependencyObject contentObject) { var itemsSourceProperty = contentObject.GetFieldValue("ItemsSourceProperty"); return contentObject == null ? null : contentObject.GetValue(itemsSourceProperty); } private static void UpdateBusyIndicator(DependencyObject busyIndicator, DependencyObject contentObject) { if (busyIndicator == null) return; if (contentObject == null) busyIndicator.SetPropValue("IsBusy", false); else { var itemsSource = contentObject == null ? null : contentObject.GetValue(GetItemsSourceValue(contentObject)); busyIndicator.SetPropValue("IsBusy", itemsSource == null); } } private static void ItemsSourceChangedCallback(DependencyObject contentObject, DependencyPropertyChangedEventArgs e) { var busyIndicator = contentObject == null ? null : contentObject.GetValue(_busyIndicatorProperty) as DependencyObject; UpdateBusyIndicator(busyIndicator, contentObject); }
рдЗрд╕ рдХреЛрдб рдХреЛ рднреА рдХреБрдЫ рд╕реНрдкрд╖реНрдЯреАрдХрд░рдг рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:
рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ,
SetBusyIndicator
рд╡рд┐рдзрд┐
dependency property ItemsSource
рдХреЛ рдЗрд╕ рддрд░рд╣ рд╕реЗ рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдИрд╡реЗрдВрдЯ рд╣реИрдВрдбрд▓рд░ рд╕реЗрдЯ рдХрд░рддреА рд╣реИ рдЬреЛ рд╣рдорд╛рд░реЗ рдкрд░рд┐рдЪрд┐рдд рд╣реИред
рджреВрд╕рд░реЗ, рдЖрдкрдХреЛ рдХрд┐рд╕реА рддрд░рд╣ рд╕реЗ
busyIndicator
рдХрдВрдЯреНрд░реЛрд▓ рдореЗрдВ
busyIndicator
рдЗрдВрд╕реНрдЯреЗрдВрд╕ рдХреЗ рд▓рд┐рдВрдХ рдХреЛ рд╕реЗрд╡ рдХрд░рдиреЗ рдХреА рдЬрд░реВрд░рдд рд╣реИ рддрд╛рдХрд┐ рдмрд╛рдж рдореЗрдВ
BusyIndicator
рдкрддрд╛
BusyIndicator
рдХрд┐
IsBusy
рд╡рд┐рд╢реЗрд╖рддрд╛ рдХреЛ рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдХреМрди рд╕рд╛
BusyIndicator
рдХрд╛ y рд╣реИред рдЗрд╕рдХреЗ рд▓рд┐рдП рд╕рдмрд╕реЗ рд╕рд░рд▓ рдФрд░ рд╕рдмрд╕реЗ рд╕реНрдкрд╖реНрдЯ рд╕рдорд╛рдзрд╛рди, рдпрд╣ рдореБрдЭреЗ рдкреНрд░рддреАрдд рд╣реБрдЖ, рдПрдХ рдФрд░ рдирд┐рдЬреА
dependency property _busyIndicatorProperty
рдХрд╛ рдЙрдкрдпреЛрдЧ
dependency property _busyIndicatorProperty
ред
рддреАрд╕рд░рд╛,
UpdateBusyIndicator
рдкрджреНрдзрддрд┐ рдореЗрдВ
UpdateBusyIndicator
рд╣рдо рдкреНрд░рддрд┐рдмрд┐рдВрдм рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ _busyIndicatorProperty рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рд╣рдорд╛рд░реЗ BusyIndicator рдХреА IsBusy рд╕рдВрдкрддреНрддрд┐ рдХрд╛ рдорд╛рди рд╕реЗрдЯ рдХрд░рддреЗ рд╣реИрдВред
рдкреВрд░реНрдг рдЙрджрд╛рд╣рд░рдг рдкрд╛рдардЖрдкрдХрд╛ рдзреНрдпрд╛рди рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рджред