Advertisement
jlind0

Untitled

Feb 17th, 2015
204
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 8.06 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Collections.ObjectModel;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. using Microsoft.Practices.Prism.Mvvm;
  8. using Microsoft.Practices.Prism.Commands;
  9. using System.Collections.Concurrent;
  10. using System.Threading;
  11.  
  12. namespace Lind.WPFTest.ViewModels
  13. {
  14.     public class MainWindowViewModel : BindableBase
  15.     {
  16.         public ObservableCollection<NavigationItem> NavigationItems { get; private set; }
  17.         private ConcurrentStack<NavigationItem> SelectedNavigationItems { get; set; }
  18.         private readonly object sync = new object();
  19.         public NavigationItem SelectedNavigationItem
  20.         {
  21.             get
  22.             {
  23.                 NavigationItem item;
  24.                 if (SelectedNavigationItems.TryPeek(out item))
  25.                     return item;
  26.                 return null;
  27.             }
  28.             set
  29.             {
  30.                 lock (sync)
  31.                 {
  32.                     NavigationItem item;
  33.                     SelectedNavigationItems.TryPeek(out item);
  34.                     if (item != value)
  35.                     {
  36.                         NavigationItem previous;
  37.                         if (SelectedNavigationItems.TryPop(out previous))
  38.                             previous.Unload();
  39.                         SelectedNavigationItems.Push(value);
  40.                         this.OnPropertyChanged(() => this.SelectedNavigationItem);
  41.                         value.Load();
  42.                     }
  43.                 }
  44.             }
  45.         }
  46.         public MainWindowViewModel()
  47.         {
  48.             if (DispatcherLocator.Dispatcher == null)
  49.                 throw new ArgumentException("The dispatcher must be set before using this class");
  50.             SelectedNavigationItems = new ConcurrentStack<NavigationItem>();
  51.             NavigationItems = new ObservableCollection<NavigationItem>() { new CarItems("Cars"), new WidgetItems("Widgets") };
  52.             SelectedNavigationItem = NavigationItems.First();
  53.         }
  54.     }
  55.     public class CancelableTask : Task
  56.     {
  57.         protected CancelableTask(Action action, CancellationTokenSource source) : base(action, source.Token)
  58.         {
  59.             Source = source;
  60.         }
  61.        
  62.         public CancellationToken Token { get { return Source.Token; } }
  63.         public void Cancel(bool throwOnFirstException = true)
  64.         {
  65.             this.Source.Cancel(throwOnFirstException);
  66.         }
  67.         private CancellationTokenSource Source { get; set; }
  68.         public static CancelableTask Run(Action<CancellationToken> action)
  69.         {
  70.             CancelableTask task = Create(action);
  71.             task.Start();
  72.             return task;
  73.         }
  74.         public static CancelableTask Create(Action<CancellationToken> action)
  75.         {
  76.             CancellationTokenSource source = new CancellationTokenSource();
  77.             CancelableTask task = new CancelableTask(() => action(source.Token), source);
  78.             return task;
  79.         }
  80.     }
  81.     public abstract class NavigationItem
  82.     {
  83.         public string NavigationItemName { get; private set; }
  84.         public NavigationItem(string name)
  85.         {
  86.             NavigationItemName = name;
  87.         }
  88.         protected CancelableTask LoadWorker { get; set; }
  89.         protected Task UnloadWorker { get; set; }
  90.         public event EventHandler Unloading;
  91.         public event EventHandler Unloaded;
  92.         public event EventHandler Loading;
  93.         public event EventHandler Loaded;
  94.         protected void RaiseUnloading()
  95.         {
  96.             if(Unloading != null)
  97.                 Unloading(this, new EventArgs());
  98.         }
  99.         protected void RaiseUnloaded()
  100.         {
  101.             if (Unloaded != null)
  102.                 Unloaded(this, new EventArgs());
  103.         }
  104.         protected void RaiseLoading()
  105.         {
  106.             if (Loading != null)
  107.                 Loading(this, new EventArgs());
  108.         }
  109.         protected void RaiseLoaded()
  110.         {
  111.             if (Loaded != null)
  112.                 Loaded(this, new EventArgs());
  113.         }
  114.         protected async Task WaitLoad()
  115.         {
  116.             if (LoadWorker != null)
  117.             {
  118.                 try
  119.                 {
  120.                     await LoadWorker;
  121.                 }
  122.                 catch(OperationCanceledException) { } //task canceled
  123.             }
  124.         }
  125.         protected async Task WaitUnload()
  126.         {
  127.             if (UnloadWorker != null)
  128.                 await UnloadWorker;
  129.         }
  130.         public abstract void Load();
  131.         public abstract void Unload();
  132.     }
  133.     public abstract class NavigationItem<T> : NavigationItem
  134.     {
  135.         public NavigationItem(string name) : base(name)
  136.         {
  137.             Items = new ObservableCollection<T>();
  138.         }
  139.         public ObservableCollection<T> Items { get; private set; }
  140.         public override async void Unload()
  141.         {
  142.             await DoUnload();
  143.         }
  144.         private async Task DoUnload()
  145.         {
  146.             await WaitUnload();
  147.             RaiseUnloading();
  148.             UnloadWorker = Task.Run(() =>
  149.             {
  150.                 if (LoadWorker != null)
  151.                     LoadWorker.Cancel();
  152.                 WaitLoad().Wait();
  153.                 DispatcherLocator.Dispatcher.Invoke(() => Items.Clear());
  154.             });
  155.             await UnloadWorker;
  156.             RaiseUnloaded();
  157.            
  158.         }
  159.         protected abstract Task<IEnumerable<T>> GetData();
  160.         public override async void Load()
  161.         {
  162.             await DoLoad();
  163.         }
  164.        
  165.         private async Task DoLoad()
  166.         {
  167.             RaiseLoading();
  168.             await WaitUnload();
  169.             LoadWorker = CancelableTask.Run(token =>
  170.             {
  171.                 token.ThrowIfCancellationRequested();
  172.                 Task.Delay(2000).Wait();
  173.                 token.ThrowIfCancellationRequested();
  174.                 var dataTask = GetData();
  175.                 dataTask.Wait();
  176.                
  177.                 token.ThrowIfCancellationRequested();
  178.                 DispatcherLocator.Dispatcher.Invoke(() =>
  179.                 {
  180.                     foreach (var item in dataTask.Result)
  181.                     {
  182.                         Items.Add(item);
  183.                     }
  184.                 });
  185.                 token.ThrowIfCancellationRequested();
  186.                 RaiseLoaded();
  187.             });
  188.             try
  189.             {
  190.                 await LoadWorker;
  191.             }
  192.             catch (OperationCanceledException) { }//task canceled
  193.            
  194.  
  195.         }
  196.     }
  197.     public class CarItems : NavigationItem<Car>
  198.     {
  199.         public CarItems(string name) : base(name) { }
  200.         protected override async Task<IEnumerable<Car>> GetData()
  201.         {
  202.             return await Task<IEnumerable<Car>>.Run(() => new Car[] {new Car() { ModelName = "Escort", Manufacturer = "Ford", ModelYear = 2002 }, new Car() { ModelName = "Focus", Manufacturer = "Ford", ModelYear = 2004 }});
  203.         }
  204.     }
  205.     public class WidgetItems : NavigationItem<Widget>
  206.     {
  207.         public WidgetItems(string name) : base(name) { }
  208.         protected override async Task<IEnumerable<Widget>> GetData()
  209.         {
  210.             Random rand = new Random();
  211.             return await Task<IEnumerable<Widget>>.Run(() => new Widget[] { new Widget() { Color = "Red", Name = "Hammer", Type = "Tool", Weight = 1.5 }, new Widget() { Color = "Black", Name = "Screw Driver", Type = "Tool", Weight = rand.Next(1, 5) } });
  212.         }
  213.     }
  214.     public interface IDispatcher
  215.     {
  216.         void Invoke(Action action);
  217.     }
  218.     public static class DispatcherLocator
  219.     {
  220.         public static IDispatcher Dispatcher { get; set; }
  221.     }
  222.     public class Car
  223.     {
  224.         public string ModelName { get; set; }
  225.         public string Manufacturer { get; set; }
  226.         public int ModelYear { get; set; }
  227.     }
  228.     public class Widget
  229.     {
  230.         public string Name { get; set; }
  231.         public string Type { get; set; }
  232.         public string Color { get; set; }
  233.         public double Weight { get; set; }
  234.     }
  235. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement