diff --git a/samples/ControlCatalog/App.paml.cs b/samples/ControlCatalog/App.paml.cs
index b1aa671215..8a49ae20f1 100644
--- a/samples/ControlCatalog/App.paml.cs
+++ b/samples/ControlCatalog/App.paml.cs
@@ -5,6 +5,7 @@ using Perspex.Controls;
using Perspex.Diagnostics;
using Perspex.Markup.Xaml;
using Perspex.Themes.Default;
+using Serilog;
namespace ControlCatalog
{
@@ -14,6 +15,7 @@ namespace ControlCatalog
{
RegisterServices();
InitializeSubsystems(GetPlatformId());
+ InitializeLogging();
Styles = new DefaultTheme();
InitializeComponent();
}
@@ -38,6 +40,16 @@ namespace ControlCatalog
PerspexXamlLoader.Load(this);
}
+ private void InitializeLogging()
+ {
+#if DEBUG
+ Log.Logger = new LoggerConfiguration()
+ .MinimumLevel.Error()
+ .WriteTo.Trace(outputTemplate: "{Message}")
+ .CreateLogger();
+#endif
+ }
+
private int GetPlatformId()
{
var args = Environment.GetCommandLineArgs();
diff --git a/samples/ControlCatalog/ControlCatalog.csproj b/samples/ControlCatalog/ControlCatalog.csproj
index 1a26286147..d3bf036619 100644
--- a/samples/ControlCatalog/ControlCatalog.csproj
+++ b/samples/ControlCatalog/ControlCatalog.csproj
@@ -36,6 +36,14 @@
+
+ ..\..\packages\Serilog.1.5.9\lib\net45\Serilog.dll
+ True
+
+
+ ..\..\packages\Serilog.1.5.9\lib\net45\Serilog.FullNetFx.dll
+ True
+
@@ -93,6 +101,7 @@
Designer
+
diff --git a/samples/ControlCatalog/packages.config b/samples/ControlCatalog/packages.config
new file mode 100644
index 0000000000..76c9b4d2a5
--- /dev/null
+++ b/samples/ControlCatalog/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/src/Perspex.Base/PriorityValue.cs b/src/Perspex.Base/PriorityValue.cs
index e45eba172f..b68fae1869 100644
--- a/src/Perspex.Base/PriorityValue.cs
+++ b/src/Perspex.Base/PriorityValue.cs
@@ -224,26 +224,29 @@ namespace Perspex
/// The priority level that the value came from.
private void UpdateValue(object value, int priority)
{
- if (TypeUtilities.TryCast(_valueType, value, out value))
+ object castValue;
+
+ if (TypeUtilities.TryCast(_valueType, value, out castValue))
{
var old = _value;
- if (_validate != null && value != PerspexProperty.UnsetValue)
+ if (_validate != null && castValue != PerspexProperty.UnsetValue)
{
- value = _validate(value);
+ castValue = _validate(castValue);
}
ValuePriority = priority;
- _value = value;
+ _value = castValue;
_changed.OnNext(Tuple.Create(old, _value));
}
else if (_logger != null)
{
_logger.Error(
- "Binding produced invalid value for {$Type} {$Property}: {$Value}",
- _valueType,
+ "Binding produced invalid value for {$Property} ({$PropertyType}): {$Value} ({$ValueType})",
_name,
- value);
+ _valueType,
+ value,
+ value.GetType());
}
}
diff --git a/src/Perspex.Base/Threading/DispatcherTimer.cs b/src/Perspex.Base/Threading/DispatcherTimer.cs
index 376ca5c0c9..1ece331c13 100644
--- a/src/Perspex.Base/Threading/DispatcherTimer.cs
+++ b/src/Perspex.Base/Threading/DispatcherTimer.cs
@@ -146,6 +146,33 @@ namespace Perspex.Threading
return Disposable.Create(() => timer.Stop());
}
+ ///
+ /// Runs a method once, after the specified interval.
+ ///
+ ///
+ /// The method to call after the interval has elapsed.
+ ///
+ /// The interval after which to call the method.
+ /// The priority to use.
+ /// An used to cancel the timer.
+ public static IDisposable RunOnce(
+ Action action,
+ TimeSpan interval,
+ DispatcherPriority priority = DispatcherPriority.Normal)
+ {
+ var timer = new DispatcherTimer(priority) { Interval = interval };
+
+ timer.Tick += (s, e) =>
+ {
+ action();
+ timer.Stop();
+ };
+
+ timer.Start();
+
+ return Disposable.Create(() => timer.Stop());
+ }
+
///
/// Starts the timer.
///
diff --git a/src/Perspex.Controls/Generators/ItemContainerEventArgs.cs b/src/Perspex.Controls/Generators/ItemContainerEventArgs.cs
index 86e2b890d1..0a9c3544d7 100644
--- a/src/Perspex.Controls/Generators/ItemContainerEventArgs.cs
+++ b/src/Perspex.Controls/Generators/ItemContainerEventArgs.cs
@@ -12,6 +12,19 @@ namespace Perspex.Controls.Generators
///
public class ItemContainerEventArgs : EventArgs
{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The index of the first container in the source items.
+ /// The container.
+ public ItemContainerEventArgs(
+ int startingIndex,
+ ItemContainer container)
+ {
+ StartingIndex = startingIndex;
+ Containers = new[] { container };
+ }
+
///
/// Initializes a new instance of the class.
///
diff --git a/src/Perspex.Controls/Generators/TreeContainerIndex.cs b/src/Perspex.Controls/Generators/TreeContainerIndex.cs
index 9de4ca1050..ab07cb454d 100644
--- a/src/Perspex.Controls/Generators/TreeContainerIndex.cs
+++ b/src/Perspex.Controls/Generators/TreeContainerIndex.cs
@@ -1,6 +1,7 @@
// Copyright (c) The Perspex Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
+using System;
using System.Collections.Generic;
namespace Perspex.Controls.Generators
@@ -19,6 +20,16 @@ namespace Perspex.Controls.Generators
private readonly Dictionary