рд╡реНрдпрд╕реНрдд рдХрджрдо рдХреЗ рд▓рд┐рдП рд╕рдВрд▓рдЧреНрди рд╕рдВрдкрддреНрддрд┐ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХрджрдо рд╕реЗ рдХрджрдо

рдпрд╣ рд▓реЗрдЦ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рд╕рдВрдЪрд╛рд▓рди рдФрд░ рдЕрдзрд┐рдХ рдХреЗ рд▓рд┐рдП рд╕реНрд╡рдЪрд╛рд▓рд┐рдд 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 рд╕рдВрдкрддреНрддрд┐ рдХрд╛ рдорд╛рди рд╕реЗрдЯ рдХрд░рддреЗ рд╣реИрдВред

рдкреВрд░реНрдг рдЙрджрд╛рд╣рд░рдг рдкрд╛рда

рдЖрдкрдХрд╛ рдзреНрдпрд╛рди рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рджред

Source: https://habr.com/ru/post/In142127/


All Articles