Skip to content

Instantly share code, notes, and snippets.

@Athari
Created July 26, 2016 23:44
Show Gist options
  • Save Athari/3f47f24d2b37cd8c0c8992c89a6bb38f to your computer and use it in GitHub Desktop.
Save Athari/3f47f24d2b37cd8c0c8992c89a6bb38f to your computer and use it in GitHub Desktop.
AwaitableCaliburnExample
<Application x:Class="AwaitableCaliburnExample.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:AwaitableCaliburnExample">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Styles.xaml"/>
<ResourceDictionary>
<local:AppBootstrapper x:Key="Bootstrapper"/>
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
using System;
using System.Collections.Generic;
using System.Windows;
using Caliburn.Micro;
namespace AwaitableCaliburnExample
{
public class AppBootstrapper : BootstrapperBase
{
private SimpleContainer _container;
public AppBootstrapper ()
{
Initialize();
}
protected override void Configure ()
{
var cfg = new TypeMappingConfiguration {
ViewModelSuffix = "Model",
ViewSuffixList = { "Window" },
IncludeViewSuffixInViewModelNames = false,
};
ViewLocator.ConfigureTypeMappings(cfg);
ViewModelLocator.ConfigureTypeMappings(cfg);
_container = new SimpleContainer()
.Singleton<IWindowManager, WindowManager>()
.Singleton<IEventAggregator, EventAggregator>();
}
protected override object GetInstance (Type service, string key) => _container.GetInstance(service, key) ?? Activator.CreateInstance(service);
protected override IEnumerable<object> GetAllInstances (Type service) => _container.GetAllInstances(service);
protected override void BuildUp (object instance) => _container.BuildUp(instance);
protected override void OnStartup (object sender, StartupEventArgs e) => DisplayRootViewFor<ShellModel>();
}
}
using System;
using System.Threading;
using System.Threading.Tasks;
namespace AwaitableCaliburnExample
{
public class ExecutionModel : StepModel
{
private string _status;
private CancellationTokenSource _cancel;
public Parameter Parameter { get; }
public ExecutionModel (Parameter parameter)
{
Parameter = parameter;
}
public string Status
{
get { return _status; }
set { Set(ref _status, value); }
}
public override async Task LoadAsync ()
{
_cancel = new CancellationTokenSource();
string from = Parameter.FromPath;
string to = Parameter.ToPath;
for (double progress = 0; progress < 1.0; progress = Math.Min(progress + 0.33333333, 1.0)) {
Status = $"Copying {from} to {to} ({progress:P} ready)";
await Task.Delay(1000, _cancel.Token);
}
Status = $"Copying {from} to {to} (100% ready)";
}
public override async Task CancelAsync () => _cancel.Cancel();
}
}
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using JetBrains.Annotations;
namespace AwaitableCaliburnExample
{
public class ModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
public virtual void OnPropertyChanged ([CallerMemberName] string propName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
}
[NotifyPropertyChangedInvocator]
public virtual void OnPropertyChanged (params string[] propNames)
{
foreach (string prop in propNames)
OnPropertyChanged(prop);
}
[NotifyPropertyChangedInvocator ("propName")]
protected bool Set<T> (ref T field, T value, [CallerMemberName] string propName = null)
{
if (EqualityComparer<T>.Default.Equals(field, value))
return false;
field = value;
OnPropertyChanged(propName);
return true;
}
[NotifyPropertyChangedInvocator ("propNames")]
protected bool Set<T> (ref T field, T value, params string[] propNames)
{
if (EqualityComparer<T>.Default.Equals(field, value))
return false;
field = value;
OnPropertyChanged(propNames);
return true;
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Caliburn.Micro" version="3.0.1" targetFramework="net452" />
<package id="Caliburn.Micro.Core" version="3.0.1" targetFramework="net452" />
<package id="Caliburn.Micro.Start" version="3.0.1" targetFramework="net452" />
</packages>
namespace AwaitableCaliburnExample
{
public class Parameter : ModelBase
{
private string _fromPath = "From\\Path";
private string _toPath = "To\\Path";
public string FromPath
{
get { return _fromPath; }
set { Set(ref _fromPath, value); }
}
public string ToPath
{
get { return _toPath; }
set { Set(ref _toPath, value); }
}
}
}
namespace AwaitableCaliburnExample
{
public class ParameterEditModel : StepModel
{
public Parameter Parameter { get; }
public ParameterEditModel (Parameter parameter)
{
Parameter = parameter;
}
}
}
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
namespace AwaitableCaliburnExample
{
public class ShellModel : ModelBase
{
private StepModel _currentStep;
private int _currentStepIndex;
private StepState _state;
public ObservableCollection<StepModel> Steps { get; }
public ShellModel ()
{
var parameter = new Parameter();
Steps = new ObservableCollection<StepModel> {
new ParameterEditModel(parameter),
new ExecutionModel(parameter),
};
CurrentStep = Steps.First();
}
public bool CanCancel => State != StepState.Finished;
public bool CanGoNext => State != StepState.Working;
public string NextLabel => State == StepState.Finished ? "Finish" : "Next";
private StepState State
{
get { return _state; }
set { Set(ref _state, value, nameof(CanCancel), nameof(CanGoNext), nameof(NextLabel)); }
}
public StepModel CurrentStep
{
get { return _currentStep; }
set { Set(ref _currentStep, value); }
}
public async Task CancelAsync ()
{
if (!CanCancel)
return;
if (State != StepState.Working)
Application.Current.Shutdown();
await CurrentStep.CancelAsync();
State = StepState.Finished;
}
public virtual async Task GoNextAsync ()
{
if (!CanGoNext)
return;
State = StepState.Working;
await CurrentStep.GoNextAsync();
CurrentStep = Steps.ElementAtOrDefault(++_currentStepIndex);
if (CurrentStep == null)
Application.Current.Shutdown();
await CurrentStep.LoadAsync();
State = CurrentStep == Steps.Last() ? StepState.Finished : StepState.Idle;
}
private enum StepState
{
Idle,
Working,
Finished,
}
}
}
<Window x:Class="AwaitableCaliburnExample.ShellWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:AwaitableCaliburnExample"
xmlns:cal="http://www.caliburnproject.org"
mc:Ignorable="d"
Title="ShellWindow" Height="200" Width="400"
d:DataContext="{d:DesignInstance local:ShellModel, IsDesignTimeCreatable=True}">
<Window.Resources>
<DataTemplate DataType="{x:Type local:ParameterEditModel}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" MinWidth="80"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="From"/>
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Parameter.FromPath}"/>
<TextBlock Grid.Row="1" Grid.Column="0" Text="To"/>
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Parameter.ToPath}"/>
</Grid>
</DataTemplate>
<DataTemplate DataType="{x:Type local:ExecutionModel}">
<TextBlock Text="{Binding Status}"/>
</DataTemplate>
</Window.Resources>
<DockPanel Margin="4" LastChildFill="False">
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal" HorizontalAlignment="Right">
<Button Content="Cancel" cal:Message.Attach="CancelAsync"/>
<Button Content="{Binding NextLabel}" cal:Message.Attach="GoNextAsync"/>
</StackPanel>
<ContentControl DockPanel.Dock="Top" Content="{Binding CurrentStep}"/>
</DockPanel>
</Window>
using System.Threading.Tasks;
namespace AwaitableCaliburnExample
{
public abstract class StepModel : ModelBase
{
public virtual Task CancelAsync () => Task.CompletedTask;
public virtual Task LoadAsync () => Task.CompletedTask;
public virtual Task GoNextAsync () => Task.CompletedTask;
}
}
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="Button">
<Setter Property="Margin" Value="4"/>
<Setter Property="MinWidth" Value="80"/>
</Style>
<Style TargetType="TextBlock">
<Setter Property="Margin" Value="4"/>
<Setter Property="VerticalAlignment" Value="Center"/>
</Style>
<Style TargetType="TextBox">
<Setter Property="Margin" Value="4"/>
</Style>
</ResourceDictionary>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment