BusyIndi​​catorをどのように実行したすか

BusyIndi​​catorに関する最近の投皿に応えお、この問題に関する圌の経隓/ビゞョンを共有するこずにしたした。 私の意芋では、この蚘事は雇甚管理の指暙のより単玔な実装を瀺しおいたす。 今では誰もが由緒ある開発䌚瀟の既補品を䜿甚できたすが、この堎合の「挏れやすい抜象化」の問題は非垞に緊急になりたす。 既成の指暙を䞍自然な方法で䜿甚するず、必然的に悲惚な結果に぀ながりたす。 したがっお、「どのように機胜するか」を想像するこずは非垞に重芁です。



Otma3ka







問題の声明



はい、しかし...䞎えられた





メむンりィンドり



<Window x:Class="MyBusyAdorner.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:views="clr-namespace:MyBusyAdorner.Views" xmlns:adorners="clr-namespace:MyBusyAdorner.Adorners" Title="MainWindow" Height="350" Width="525"> <Grid> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <views:BaseAdornableControl x:Name="AdornableControl" BusyAdorner="{x:Null}" Margin="15"/> <Button Content="Attach/Detach" Grid.Row="1" Click="Button_Click"/> </Grid> </Window>
      
      





 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using MyBusyAdorner.ViewModels; using MyBusyAdorner.Adorners; namespace MyBusyAdorner { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { private SimpleBusyAdornerDemoViewModel _viewModel; public MainWindow() { InitializeComponent(); DataContext = _viewModel = new SimpleBusyAdornerDemoViewModel(); _viewModel.IsBusyChanged = new Action<bool>((newValue) => { AttachDetachBusyAdorner(newValue); }); } private void AttachDetachBusyAdorner(bool isBusy) { AdornableControl.BusyAdorner = isBusy ? new BusyAdorner(AdornableControl) : null; } private void Button_Click(object sender, RoutedEventArgs e) { _viewModel.IsBusy = !_viewModel.IsBusy; } } }
      
      





ここではすべおが簡単です。 りィンドりには、マヌクするフォヌムがありたす。 その䞋には、ViewModelのIsBusyプロパティの倀を倉曎するボタンがありたす。 すでに曞いたように、このボタンはタスクの開始ず終了を暡倣したす非同期。 この堎合、非同期タスクずViewModelの盞互䜜甚のロゞックがどのように実装されるかは重芁ではありたせん。 TPLラむブラリが䜿甚されおいるず仮定したすずころで、これは私のmcDonnaldsです-「私はLovinだから...」。 メむンりィンドりのデザむナヌで、 IsBusy倉曎サブスクリプションがアクションに䜜成されたした。 この堎合、ハンドラヌは1぀だけなので、Actionを䜿甚できたす。 それ以倖の堎合は、デリゲヌトを省略できたせんでした。 そのため、ハンドラヌはAdornableControlのBusyAdorner倀を蚭定したすむンゞケヌタヌを切断する堎合はnull、アタッチする堎合はnullではありたせん。



Busyadorner



 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Documents; using System.Windows; using System.Windows.Media; namespace MyBusyAdorner.Adorners { public class BusyAdorner : Adorner { public BusyAdorner(UIElement adornedElement) : base(adornedElement) { } protected override void OnRender(DrawingContext drawingContext) { var adornedControl = this.AdornedElement as FrameworkElement; if (adornedControl == null) return; Rect rect = new Rect(0,0, adornedControl.ActualWidth, adornedControl.ActualHeight); // Some arbitrary drawing implements. SolidColorBrush renderBrush = new SolidColorBrush(Colors.Green); renderBrush.Opacity = 0.2; Pen renderPen = new Pen(new SolidColorBrush(Colors.Navy), 1.5); double renderRadius = 5.0; double dist = 15; double cntrX = rect.Width / 2; double cntrY = rect.Height / 2; double left = cntrX - dist; double right = cntrX + dist; double top = cntrY - dist; double bottom = cntrY + dist; // Draw four circles near to center. drawingContext.PushTransform(new RotateTransform(45, cntrX, cntrY)); drawingContext.DrawEllipse(renderBrush, renderPen, new Point { X = left, Y = top}, renderRadius, renderRadius); drawingContext.DrawEllipse(renderBrush, renderPen, new Point { X = right, Y = top }, renderRadius, renderRadius); drawingContext.DrawEllipse(renderBrush, renderPen, new Point { X = right, Y = bottom }, renderRadius, renderRadius); drawingContext.DrawEllipse(renderBrush, renderPen, new Point { X = left, Y = bottom }, renderRadius, renderRadius); } } }
      
      





これは䞀皮の「ひねり」であり、雇甚ViewModelを瀺す䞍気味な蚘念碑を生成するこずが理解されたす。 この堎合、画像は静的になりたすが、回転ダむナミクスがRotateTransformの角床を曎新するための十分なタむマヌがありたせん。 ここでは、アニメヌションの想像力を開攟できたす。 ちなみに、TPLの同じタスクを䜿甚しお、画像の回転角床をスムヌズに倉曎できたすHMM ... ゲヌムルヌプずしおのタスク詊しおみおください 。

したがっお、次のようになりたす。



神は䜕を知っおいるのではありたせんが、抂念のデモンストレヌションずしお降りおきたす。



BaseAdornableControl



 <!--    ... ..     -->
      
      





 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using MyBusyAdorner.Adorners; namespace MyBusyAdorner.Views { /// <summary> /// Interaction logic for BaseAdornableControl.xaml /// </summary> public partial class BaseAdornableControl : UserControl { #region [Fields] //private List<Adorner> _adorners = new List<Adorner>(); private BusyAdorner _busyAdorner; #endregion [/Fields] #region [Properties] public BusyAdorner BusyAdorner { get { return _busyAdorner; } set { DetachBusyAdorner(); _busyAdorner = value; if (value != null) { AttachBusyAdorner(); } } } private void AttachBusyAdorner() { if (_busyAdorner == null) return; var adornerLayer = AdornerLayer.GetAdornerLayer(this); adornerLayer.Add(_busyAdorner); } private void DetachBusyAdorner() { var adornerLayer = AdornerLayer.GetAdornerLayer(this); if (adornerLayer != null && _busyAdorner != null) { adornerLayer.Remove(_busyAdorner); } } #endregion [/Properties] public BaseAdornableControl() { InitializeComponent(); this.Unloaded += new RoutedEventHandler(BaseAdornableControl_Unloaded); } void BaseAdornableControl_Unloaded(object sender, RoutedEventArgs e) { DetachBusyAdorner(); } } }
      
      





重芁なお知らせ 。 装食にラップされたコントロヌルをアンロヌドする前に、装食を眪メモリリヌクから切り離す必芁がありたす。 AdornerLayerのロゞックは非垞に耇雑であり、譊戒心を倱うず、レヌキをかけるこずができたす。 だから私はあなたに譊告したした...



SimpleBusyAdornerDemoViewModel



 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ComponentModel; namespace MyBusyAdorner.ViewModels { public class SimpleBusyAdornerDemoViewModel : INotifyPropertyChanged { #region [Fields] private bool _isBusy; #endregion [/Fields] #region [Properties] public bool IsBusy { get { return _isBusy; } set { if (value != _isBusy) { _isBusy = value; RaisePropertyChanged("IsBusy"); RaiseIsBusyChanged(); } } } public Action<bool> IsBusyChanged { get; set; } #endregion [/Properties] #region [Private Methods] private void RaiseIsBusyChanged() { if (IsBusyChanged != null) { IsBusyChanged(_isBusy); } } #endregion [/Private Methods] #region [INotifyPropertyChanged] public event PropertyChangedEventHandler PropertyChanged; private void RaisePropertyChanged(string propertyName) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } #endregion [/INotifyPropertyChanged] } }
      
      





eventの代わりにActionを持぀「WTF-code」を陀いお、MVVMパタヌンに粟通しおいる人にずっお特別なこずはありたせん。



远加機胜-BusyAdornerManager



 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Collections.ObjectModel; using MyBusyAdorner.Adorners; using System.Windows; using System.Windows.Documents; namespace MyBusyAdorner.Services { public sealed class BusyAdornerManager { #region [Fieds] private List<BusyAdorner> _adorners; #endregion [/Fieds] #region [Public Methods] public void AddBusyAdorner(UIElement adornedElement) { if (adornedElement == null) return; var adorner = new BusyAdorner(adornedElement); _adorners.Add(adorner); } public void RemoveAllAdorners(UIElement adornedElement) { if (adornedElement == null) return; var adornerLayer = AdornerLayer.GetAdornerLayer(adornedElement); foreach (var adorner in adornerLayer.GetAdorners(adornerLayer)) { adornerLayer.Remove(adorner); } } #endregion [/Public Methods] #region Singleton private static volatile BusyAdornerManager instance; private static object syncRoot = new Object(); private BusyAdornerManager() { } public static BusyAdornerManager Instance { get { if (instance == null) { lock (syncRoot) { if (instance == null) instance = new BusyAdornerManager(); } } return instance; } } #endregion } }
      
      





これは、任意のコントロヌルに装食をぶら䞋げられるように蚭蚈されたサヌビスです。 たた、kakulka-それはシングルトンではなく、単なる静的なクラスにするこずができ、アドレナヌのリストはただ䟡倀がありたせん。

おわりに



gitやその他のポむントが芋圓たらない堎所に広めお、率盎に蚀っお、このような些现なこずを台無しにしたくない。 私にずっお、この投皿はスニペットであり、思考/知識を敎理する詊みであり、habreviewボヌドぞのチケットです。 しかし、おそらく誰かが䟿利だず思うでしょう。 それで私たちは健康を批刀したす。「コヌドスタむルのガむド」に぀いおはホリバヌなしで...



UPD



継承のオヌバヌヘッドの問題に぀いお ...フォヌムのビュヌは䞀般にUserControlです。 UserControlの代わりにUserControlExたたは同じBaseAdornableControlなどのXAMLで蚘述するこずは本圓に可胜ですか倧きなオヌバヌヘッドですか



玔粋にMVVMアプロヌチを䜿甚するずいう質問に ... DependencyPropertyをBaseAdornableControlに远加し、IsBusy ViewModelにバむンドするのは簡単です。 このプロパティを倉曎するハンドラで、倖郚から泚文したのず同じこずを行いたす。 これは、サヌドパヌティ補品の内郚特性を反映した束葉杖を構築するよりもはるかに信頌性がありたす。 サヌドパヌティの開発者が自分自身の内郚を倉えるこずをどう思うか誰が知っおいたすか



アドナヌをViewModelプロパティに盎接バむンドする問題に぀いお ...解説で曞いたように、DependencyPropertyを含める必芁がありたす。そのためには、たずえば、アドナヌをFrameworkElementから継承する必芁がありたす。 そしお、これは非垞に深刻なオヌバヌヘッドになりたす。特に、装食者が垞にメモリにハングアップする堎合です。

Visifireコヌドをお楜しみください 。 たたは、少なくずもSNOOP'omはBarChart'aツリヌを歩きたす。 そこで、チャヌトの各バヌに察しお、1぀たたは2぀の䞭間キャンバスが䜜成されたす。 さらに、DataPointはFrameworkElementを継承し、DataPointを䜕かにバむンドするか、 Colorプロパティを蚭定したすこれはColorではなく、Brushではありたせん。 そしお冗談は、これらのDataPointsはFrameworkElementsであり、チャヌトのキャンバスに配眮されるずいうこずです。 それらに、FrameworkElementsのもう1぀のコレクションが新しく䜜成され、描画されたす。 その結果、Visifireチャヌトはすでに600以䞊の芁玠でブレヌキをかけ始めおいたす。 比范のために動的デヌタ衚瀺->折れ線グラフ-> 60k芁玠特に滑らかなグラフィックス->通垞描画されたす。

したがっお、ViewModelに盎接バむンダヌを決定するず、たったく䞍芁なオヌバヌヘッドが発生したす。



UPD2



ToolKitむンディケヌタヌの䜿甚に関する質問に ...

コメントがありたす...読んでください。 たずえば、次のコヌド

 BackgroundWorker worker = new BackgroundWorker(); worker.DoWork += (o, ea) => { //long-running-process code System.Threading.Thread.Sleep(10000); DispatchService.Dispatch((Action)(() => { //update the UI code goes here // ... })); }; worker.RunWorkerCompleted += (o, ea) => { this.ResetIsBusy(); //here the BusyIndicator.IsBusy is set to FALSE }; this.SetIsBusy(); //here the BusyIndicator.IsBusy is set to TRUE worker.RunWorkerAsync();
      
      





そこで衚瀺されるむンゞケヌタは、基本的に、非同期タスクの進行状況をナヌザヌに通知するために蚭蚈された特別なダむアログです。 このダむアログは、りィンドり/アプリケヌション党䜓で実行されたす。 ここに衚瀺されるむンゞケヌタは、メモリ消費量が高くなるこずを恐れずに、コントロヌルごずに個別にハングアップできたす。 異なるカテゎリヌ。



All Articles