Otma3ka
-
wKodilãã BusyIndiââcator ãã«é¢ããè¿é£ã®æçš¿ã«è§Šçºãã㊠- æ¿ããç±æã§ãããã¹ããã©ã¯ãã£ã¹ã¬ã€ãããæ¯ãè¿ãããšãªãã³ãŒããæžããŸããã
- å®éãã¬ãã¹ã³ãã©ãã ãããåŠã³ãå éšã®ã 10k Clock ããæŽæ°ãããã¯èå³æ·±ã
- äžèšãšå£æ» çãªæéäžè¶³ã®ãããã³ãŒãã¯åªé ã«èŒããŸãã
- ãŸããã³ãŒãã¯æ®éçã§ã¯ãããŸããã æ¢åã®ã¢ããªã±ãŒã·ã§ã³ã¢ãŒããã¯ãã£ã«çµ±åããã®ãé£ããå ŽåããããŸã
- ããããããã¯ã·ã³ãã«ã§ããããããïŒå°ãªããšãç§ã«ã¯ïŒããããŠæãéèŠãªããšã¯[åå°]åå°ããªãããšã§ã[/åå°]
åé¡ã®å£°æ
- äœããã®åœ¢åŒã®ããŒã¿å
¥åãé
眮ãããã¡ã€ã³ãŠã£ã³ããŠ
- ãŠã£ã³ããŠå ã®ãã©ãŒã ã¯ã ãããªãã¯ããããã£BusyAdorner BusyAdornerãæã€BaseAdornableControlïŒUserControl ïŒãŸãã¯åå«ïŒã¯ã©ã¹ã®ã€ã³ã¹ã¿ã³ã¹ã§ãã
- ãã®ããããã£ã®ã»ãã¿ãŒã§ã¯ãããžãŒã€ã³ãžã±ãŒã¿ãæ¥ç¶/åæãããŸã
- ã¡ã€ã³ãŠã£ã³ããŠã®DataContextã«ã¯ããã¢ViewModelã®ã€ã³ã¹ã¿ã³ã¹ã®å€ãå²ãåœãŠãããŸãïŒããã®å€æ°
Piãææã®äººã§åŒã³åºãã SimpleBusyAdornerDemoViewModel ïŒ - ViewModelã«ã¯1ã€ã®ããã³ããããã£IsBusyãããããã®ããããã£ã®å€æŽã€ãã³ãã®ä»£ããã«ã¢ã¯ã·ã§ã³[bool]ããããŸã
- ç°¡åã«ããããã«ã€ãã³ãã«ç ©ããããŸããã§ããïŒè¿œå ã®ãã³ãã©ãŒã¯ã©ã¹ãšãã®åŒæ°ã宣èšããããããŸããã§ããïŒ
- ããžãã¯ã¯æ¬¡ã®ãšããã§ããIsBusyå€ãå€æŽãããšã ã¢ã¯ã·ã§ã³[bool] IsBusyChangedãåŒæ°ãšããŠæ°ããIsBusyå€ã§äœåããŸã
- Action [bool]ãžã®ãµãã¹ã¯ã©ã€ãIsBusyChangedã¯ã BaseAdornableControlã€ã³ã¹ã¿ã³ã¹ã®BusyAdornerããããã£ã®å€ãnull ïŒã¢ãããŒãåæïŒãŸãã¯ãŒã以å€ã®å€ïŒã¢ãããŒãæ¥ç¶ïŒã«èšå®ããŸãã
- ç¹°ãè¿ããŸãããç°¡åã«ããããã«ã IsBusyå€ãViewModelã«å転ãããã¿ã³ããŠã£ã³ããŠã«é 眮ããŸããããããšãã°ãWebãµãŒãã¹ã«èŠæ±ãéä¿¡ããŠå¿çãåä¿¡ãããšããViewModelããããè¡ãå¿ èŠãããããšãç¥ã£ãŠããŸã
ã¡ã€ã³ãŠã£ã³ããŠ
<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ã瀺ã
ãããã£ãŠã次ã®ããã«ãªããŸãã
ç¥ã¯äœãç¥ã£ãŠããã®ã§ã¯ãããŸããããæŠå¿µã®ãã¢ã³ã¹ãã¬ãŒã·ã§ã³ãšããŠéããŠããŸãã
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();
ããã§è¡šç€ºãããã€ã³ãžã±ãŒã¿ã¯ãåºæ¬çã«ãéåæã¿ã¹ã¯ã®é²è¡ç¶æ³ããŠãŒã¶ãŒã«éç¥ããããã«èšèšãããç¹å¥ãªãã€ã¢ãã°ã§ãã ãã®ãã€ã¢ãã°ã¯ããŠã£ã³ããŠ/ã¢ããªã±ãŒã·ã§ã³å šäœã§å®è¡ãããŸãã ããã«è¡šç€ºãããã€ã³ãžã±ãŒã¿ã¯ãã¡ã¢ãªæ¶è²»éãé«ããªãããšãæããã«ãã³ã³ãããŒã«ããšã«åå¥ã«ãã³ã°ã¢ããã§ããŸãã ç°ãªãã«ããŽãªãŒã