Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using Microsoft.Practices.Prism.Mvvm;
- using Microsoft.Practices.Prism.Commands;
- using System.Collections.Concurrent;
- using System.Threading;
- namespace Lind.WPFTest.ViewModels
- {
- public class MainWindowViewModel : BindableBase
- {
- public ObservableCollection<NavigationItem> NavigationItems { get; private set; }
- private ConcurrentStack<NavigationItem> SelectedNavigationItems { get; set; }
- private readonly object sync = new object();
- public NavigationItem SelectedNavigationItem
- {
- get
- {
- NavigationItem item;
- if (SelectedNavigationItems.TryPeek(out item))
- return item;
- return null;
- }
- set
- {
- lock (sync)
- {
- NavigationItem item;
- SelectedNavigationItems.TryPeek(out item);
- if (item != value)
- {
- NavigationItem previous;
- if (SelectedNavigationItems.TryPop(out previous))
- previous.Unload();
- SelectedNavigationItems.Push(value);
- this.OnPropertyChanged(() => this.SelectedNavigationItem);
- value.Load();
- }
- }
- }
- }
- public MainWindowViewModel()
- {
- if (DispatcherLocator.Dispatcher == null)
- throw new ArgumentException("The dispatcher must be set before using this class");
- SelectedNavigationItems = new ConcurrentStack<NavigationItem>();
- NavigationItems = new ObservableCollection<NavigationItem>() { new CarItems("Cars"), new WidgetItems("Widgets") };
- SelectedNavigationItem = NavigationItems.First();
- }
- }
- public class CancelableTask : Task
- {
- protected CancelableTask(Action action, CancellationTokenSource source) : base(action, source.Token)
- {
- Source = source;
- }
- public CancellationToken Token { get { return Source.Token; } }
- public void Cancel(bool throwOnFirstException = true)
- {
- this.Source.Cancel(throwOnFirstException);
- }
- private CancellationTokenSource Source { get; set; }
- public static CancelableTask Run(Action<CancellationToken> action)
- {
- CancelableTask task = Create(action);
- task.Start();
- return task;
- }
- public static CancelableTask Create(Action<CancellationToken> action)
- {
- CancellationTokenSource source = new CancellationTokenSource();
- CancelableTask task = new CancelableTask(() => action(source.Token), source);
- return task;
- }
- }
- public abstract class NavigationItem
- {
- public string NavigationItemName { get; private set; }
- public NavigationItem(string name)
- {
- NavigationItemName = name;
- }
- protected CancelableTask LoadWorker { get; set; }
- protected Task UnloadWorker { get; set; }
- public event EventHandler Unloading;
- public event EventHandler Unloaded;
- public event EventHandler Loading;
- public event EventHandler Loaded;
- protected void RaiseUnloading()
- {
- if(Unloading != null)
- Unloading(this, new EventArgs());
- }
- protected void RaiseUnloaded()
- {
- if (Unloaded != null)
- Unloaded(this, new EventArgs());
- }
- protected void RaiseLoading()
- {
- if (Loading != null)
- Loading(this, new EventArgs());
- }
- protected void RaiseLoaded()
- {
- if (Loaded != null)
- Loaded(this, new EventArgs());
- }
- protected async Task WaitLoad()
- {
- if (LoadWorker != null)
- {
- try
- {
- await LoadWorker;
- }
- catch(OperationCanceledException) { } //task canceled
- }
- }
- protected async Task WaitUnload()
- {
- if (UnloadWorker != null)
- await UnloadWorker;
- }
- public abstract void Load();
- public abstract void Unload();
- }
- public abstract class NavigationItem<T> : NavigationItem
- {
- public NavigationItem(string name) : base(name)
- {
- Items = new ObservableCollection<T>();
- }
- public ObservableCollection<T> Items { get; private set; }
- public override async void Unload()
- {
- await DoUnload();
- }
- private async Task DoUnload()
- {
- await WaitUnload();
- RaiseUnloading();
- UnloadWorker = Task.Run(() =>
- {
- if (LoadWorker != null)
- LoadWorker.Cancel();
- WaitLoad().Wait();
- DispatcherLocator.Dispatcher.Invoke(() => Items.Clear());
- });
- await UnloadWorker;
- RaiseUnloaded();
- }
- protected abstract Task<IEnumerable<T>> GetData();
- public override async void Load()
- {
- await DoLoad();
- }
- private async Task DoLoad()
- {
- RaiseLoading();
- await WaitUnload();
- LoadWorker = CancelableTask.Run(token =>
- {
- token.ThrowIfCancellationRequested();
- Task.Delay(2000).Wait();
- token.ThrowIfCancellationRequested();
- var dataTask = GetData();
- dataTask.Wait();
- token.ThrowIfCancellationRequested();
- DispatcherLocator.Dispatcher.Invoke(() =>
- {
- foreach (var item in dataTask.Result)
- {
- Items.Add(item);
- }
- });
- token.ThrowIfCancellationRequested();
- RaiseLoaded();
- });
- try
- {
- await LoadWorker;
- }
- catch (OperationCanceledException) { }//task canceled
- }
- }
- public class CarItems : NavigationItem<Car>
- {
- public CarItems(string name) : base(name) { }
- protected override async Task<IEnumerable<Car>> GetData()
- {
- return await Task<IEnumerable<Car>>.Run(() => new Car[] {new Car() { ModelName = "Escort", Manufacturer = "Ford", ModelYear = 2002 }, new Car() { ModelName = "Focus", Manufacturer = "Ford", ModelYear = 2004 }});
- }
- }
- public class WidgetItems : NavigationItem<Widget>
- {
- public WidgetItems(string name) : base(name) { }
- protected override async Task<IEnumerable<Widget>> GetData()
- {
- Random rand = new Random();
- 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) } });
- }
- }
- public interface IDispatcher
- {
- void Invoke(Action action);
- }
- public static class DispatcherLocator
- {
- public static IDispatcher Dispatcher { get; set; }
- }
- public class Car
- {
- public string ModelName { get; set; }
- public string Manufacturer { get; set; }
- public int ModelYear { get; set; }
- }
- public class Widget
- {
- public string Name { get; set; }
- public string Type { get; set; }
- public string Color { get; set; }
- public double Weight { get; set; }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement