diff --git a/samples/BindingTest/App.config b/samples/BindingTest/App.config
index d1428ad712..a54d71fef0 100644
--- a/samples/BindingTest/App.config
+++ b/samples/BindingTest/App.config
@@ -1,6 +1,18 @@
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/BindingTest/App.xaml.cs b/samples/BindingTest/App.xaml.cs
index 5ffac249e9..ef5f7ba4d9 100644
--- a/samples/BindingTest/App.xaml.cs
+++ b/samples/BindingTest/App.xaml.cs
@@ -13,30 +13,20 @@ namespace BindingTest
public App()
{
RegisterServices();
- InitializeSubsystems((int)Environment.OSVersion.Platform);
- InitializeComponent();
- InitializeLogging();
- }
-
- public static void AttachDevTools(Window window)
- {
- DevTools.Attach(window);
}
private static void Main()
{
- var app = new App();
- var window = new MainWindow();
- window.Show();
- app.Run(window);
- }
+ InitializeLogging();
- private void InitializeComponent()
- {
- PerspexXamlLoader.Load(this);
+ new App()
+ .UseWin32()
+ .UseDirect2D()
+ .LoadFromXaml()
+ .RunWithMainWindow();
}
- private void InitializeLogging()
+ private static void InitializeLogging()
{
#if DEBUG
SerilogLogger.Initialize(new LoggerConfiguration()
diff --git a/samples/BindingTest/MainWindow.xaml.cs b/samples/BindingTest/MainWindow.xaml.cs
index a8e64485cb..00b46faecf 100644
--- a/samples/BindingTest/MainWindow.xaml.cs
+++ b/samples/BindingTest/MainWindow.xaml.cs
@@ -1,4 +1,5 @@
using BindingTest.ViewModels;
+using Perspex;
using Perspex.Controls;
using Perspex.Markup.Xaml;
@@ -10,12 +11,12 @@ namespace BindingTest
{
this.InitializeComponent();
this.DataContext = new MainWindowViewModel();
- App.AttachDevTools(this);
+ this.AttachDevTools();
}
private void InitializeComponent()
{
- PerspexXamlLoader.Load(this);
+ this.LoadFromXaml();
}
}
}
diff --git a/samples/ControlCatalog/App.config b/samples/ControlCatalog/App.config
index 7ef9d715f8..0c47592f2c 100644
--- a/samples/ControlCatalog/App.config
+++ b/samples/ControlCatalog/App.config
@@ -1,13 +1,21 @@
-
+
-
+
-
-
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/ControlCatalog/App.xaml.cs b/samples/ControlCatalog/App.xaml.cs
index 2930fa746a..5ee9373edb 100644
--- a/samples/ControlCatalog/App.xaml.cs
+++ b/samples/ControlCatalog/App.xaml.cs
@@ -9,58 +9,14 @@ using Serilog;
namespace ControlCatalog
{
+ // Eventually we should move this into a PCL library so we can access
+ // from mobile platforms
+ //
class App : Application
{
public App()
{
RegisterServices();
- InitializeSubsystems(GetPlatformId());
- InitializeLogging();
- InitializeComponent();
- }
-
- public static void AttachDevTools(Window window)
- {
-#if DEBUG
- DevTools.Attach(window);
-#endif
- }
-
- static void Main(string[] args)
- {
- var app = new App();
- var window = new MainWindow();
- window.Show();
- app.Run(window);
- }
-
- private void InitializeComponent()
- {
- PerspexXamlLoader.Load(this);
- }
-
- private void InitializeLogging()
- {
-#if DEBUG
- SerilogLogger.Initialize(new LoggerConfiguration()
- .MinimumLevel.Warning()
- .WriteTo.Trace(outputTemplate: "{Area}: {Message}")
- .CreateLogger());
-#endif
- }
-
- private int GetPlatformId()
- {
- var args = Environment.GetCommandLineArgs();
-
- if (args.Contains("--gtk"))
- {
- return (int)PlatformID.Unix;
- }
- else
- {
- return (int)Environment.OSVersion.Platform;
- }
}
}
}
diff --git a/samples/ControlCatalog/ControlCatalog.csproj b/samples/ControlCatalog/ControlCatalog.csproj
index 087998c805..36238efc7c 100644
--- a/samples/ControlCatalog/ControlCatalog.csproj
+++ b/samples/ControlCatalog/ControlCatalog.csproj
@@ -103,6 +103,7 @@
SliderPage.xaml
+
diff --git a/samples/ControlCatalog/MainWindow.xaml.cs b/samples/ControlCatalog/MainWindow.xaml.cs
index 5a5b7d4303..62949a9abd 100644
--- a/samples/ControlCatalog/MainWindow.xaml.cs
+++ b/samples/ControlCatalog/MainWindow.xaml.cs
@@ -1,4 +1,5 @@
-using Perspex.Controls;
+using Perspex;
+using Perspex.Controls;
using Perspex.Markup.Xaml;
namespace ControlCatalog
@@ -8,12 +9,12 @@ namespace ControlCatalog
public MainWindow()
{
this.InitializeComponent();
- App.AttachDevTools(this);
+ this.AttachDevTools();
}
private void InitializeComponent()
{
- PerspexXamlLoader.Load(this);
+ this.LoadFromXaml();
}
}
}
diff --git a/samples/ControlCatalog/Program.cs b/samples/ControlCatalog/Program.cs
new file mode 100644
index 0000000000..d01a6aa11b
--- /dev/null
+++ b/samples/ControlCatalog/Program.cs
@@ -0,0 +1,127 @@
+using Perspex.Logging.Serilog;
+using Serilog;
+using System;
+using System.Linq;
+using Perspex;
+
+namespace ControlCatalog
+{
+ internal class Program
+ {
+ static void Main(string[] args)
+ {
+ InitializeLogging();
+
+ new App()
+ .ConfigureRenderSystem(args)
+ .LoadFromXaml()
+ .RunWithMainWindow();
+ }
+
+ // This will be made into a runtime configuration extension soon!
+ private static void InitializeLogging()
+ {
+#if DEBUG
+ SerilogLogger.Initialize(new LoggerConfiguration()
+ .MinimumLevel.Warning()
+ .WriteTo.Trace(outputTemplate: "{Area}: {Message}")
+ .CreateLogger());
+#endif
+ }
+
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // Experimental: Would like to move this into a shared location once I figure out the best place for it
+ // considering all common libraries are PCL and do not have access to Environment.OSVersion.Platform
+ // nor do they have access to the platform specific render/subsystem extensions.
+ //
+ // Perhaps via DI we register each system with a priority/rank
+ //
+ public static class RenderSystemExtensions
+ {
+ [Flags]
+ enum RenderSystem
+ {
+ None = 0,
+ GTK = 1,
+ Skia = 2,
+ Direct2D = 4
+ };
+
+ ///
+ /// Default (Optimal) render system for a particular platform
+ ///
+ ///
+ private static RenderSystem DefaultRenderSystem()
+ {
+ switch (Environment.OSVersion.Platform)
+ {
+ case PlatformID.MacOSX:
+ return RenderSystem.GTK;
+
+ case PlatformID.Unix:
+ return RenderSystem.GTK;
+
+ case PlatformID.Win32Windows:
+ return RenderSystem.Direct2D;
+ }
+
+ return RenderSystem.None;
+ }
+
+ ///
+ /// Returns an array of avalidable rendering systems in priority order
+ ///
+ ///
+ private static RenderSystem[] AvailableRenderSystems()
+ {
+ switch (Environment.OSVersion.Platform)
+ {
+ case PlatformID.MacOSX:
+ return new RenderSystem[] { RenderSystem.GTK, RenderSystem.Skia };
+
+ case PlatformID.Unix:
+ return new RenderSystem[] { RenderSystem.GTK, RenderSystem.Skia };
+
+ case PlatformID.Win32Windows:
+ return new RenderSystem[] { RenderSystem.Direct2D, RenderSystem.Skia, RenderSystem.GTK };
+ }
+
+ return new RenderSystem[0];
+ }
+
+ ///
+ /// Selects the optimal render system for desktop platforms. Supports cmd line overrides
+ ///
+ ///
+ ///
+ public static TApp ConfigureRenderSystem(this TApp app, string[] args) where TApp : Application
+ {
+ // So this all works great under Windows where it can support
+ // ALL configurations. But on OSX/Unix we cannot use Direct2D
+ //
+ if (args.Contains("--gtk") || DefaultRenderSystem() == RenderSystem.GTK)
+ {
+ app.UseGtk();
+ app.UseCairo();
+ }
+ else
+ {
+ app.UseWin32();
+
+ // not available until we do the SkiaSharp merge
+ //if (args.Contains("--skia") || DefaultRenderSystem() == RenderSystem.Skia)
+ //{
+ // app.UseSkia();
+ //}
+ //else
+ {
+ app.UseDirect2D();
+ }
+ }
+
+ return app;
+ }
+ }
+}
diff --git a/samples/TestApplication/App.config b/samples/TestApplication/App.config
index 6bcf42cd00..410577105c 100644
--- a/samples/TestApplication/App.config
+++ b/samples/TestApplication/App.config
@@ -23,11 +23,11 @@
-
+
-
+
diff --git a/samples/TestApplication/Program.cs b/samples/TestApplication/Program.cs
index 7aa433bfa8..38b059afff 100644
--- a/samples/TestApplication/Program.cs
+++ b/samples/TestApplication/Program.cs
@@ -31,11 +31,30 @@ namespace TestApplication
// The version of ReactiveUI currently included is for WPF and so expects a WPF
// dispatcher. This makes sure it's initialized.
System.Windows.Threading.Dispatcher foo = System.Windows.Threading.Dispatcher.CurrentDispatcher;
- new App();
- MainWindow.RootNamespace = "TestApplication";
- var wnd = MainWindow.Create();
- DevTools.Attach(wnd);
- Application.Current.Run(wnd);
+
+ var app = new App();
+
+ if (args.Contains("--gtk"))
+ {
+ app.UseGtk();
+ app.UseCairo();
+ }
+ else
+ {
+ app.UseWin32();
+
+ // not available until we do the SkiaSharp merge
+ //if (args.Contains("--skia"))
+ //{
+ // app.UseSkia();
+ //}
+ //else
+ {
+ app.UseDirect2D();
+ }
+ }
+
+ app.Run();
}
}
}
diff --git a/samples/TestApplicationShared/App.cs b/samples/TestApplicationShared/App.cs
index 8bab852747..83987d26df 100644
--- a/samples/TestApplicationShared/App.cs
+++ b/samples/TestApplicationShared/App.cs
@@ -8,6 +8,9 @@ using Perspex.Controls.Templates;
using Perspex.Markup.Xaml;
using Perspex.Styling;
using Perspex.Themes.Default;
+using Perspex.Diagnostics;
+using Perspex.Platform;
+using Perspex.Shared.PlatformSupport;
namespace TestApplication
{
@@ -15,34 +18,35 @@ namespace TestApplication
{
public App()
{
+ // TODO: I believe this has to happen before we select sub systems. Can we
+ // move this safely into Application itself? Is there anything in here
+ // that is platform specific??
+ //
RegisterServices();
+ }
-#if !__IOS__ // IOS Startup flow is a bit different and cannot use this
- RegisterPlatformCallback(PlatformInitialization);
-#endif
-
- InitializeSubsystems((int)Environment.OSVersion.Platform);
-
+ public void Run()
+ {
Styles.Add(new DefaultTheme());
- var loader = new PerspexXamlLoader();
- var baseLight = (IStyle)loader.Load(
- new Uri("resm:Perspex.Themes.Default.Accents.BaseLight.xaml?assembly=Perspex.Themes.Default"));
- Styles.Add(baseLight);
+ var loader = new PerspexXamlLoader();
+ var baseLight = (IStyle)loader.Load(
+ new Uri("resm:Perspex.Themes.Default.Accents.BaseLight.xaml?assembly=Perspex.Themes.Default"));
+ Styles.Add(baseLight);
- Styles.Add(new SampleTabStyle());
- DataTemplates = new DataTemplates
- {
- new FuncTreeDataTemplate(
- x => new TextBlock {Text = x.Name},
- x => x.Children),
- };
- }
+ Styles.Add(new SampleTabStyle());
+ DataTemplates = new DataTemplates
+ {
+ new FuncTreeDataTemplate(
+ x => new TextBlock {Text = x.Name},
+ x => x.Children),
+ };
- protected virtual void PlatformInitialization()
- {
- // default behavior
- InitializeSubsystems((int)Environment.OSVersion.Platform);
+ MainWindow.RootNamespace = "TestApplication";
+ var wnd = MainWindow.Create();
+ DevTools.Attach(wnd);
+
+ Run(wnd);
}
}
}
diff --git a/samples/XamlTestApplication/App.config b/samples/XamlTestApplication/App.config
index ccdb787c0f..46a3a2eb27 100644
--- a/samples/XamlTestApplication/App.config
+++ b/samples/XamlTestApplication/App.config
@@ -1,33 +1,33 @@
-
+
-
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
diff --git a/samples/XamlTestApplication/App.cs b/samples/XamlTestApplication/App.cs
index 01ac91299c..9d5df3236c 100644
--- a/samples/XamlTestApplication/App.cs
+++ b/samples/XamlTestApplication/App.cs
@@ -7,26 +7,5 @@ using Serilog;
namespace XamlTestApplication
{
- public class App : XamlTestApp
- {
- public App()
- {
- InitializeLogging();
- }
-
- protected override void RegisterPlatform()
- {
- InitializeSubsystems((int)Environment.OSVersion.Platform);
- }
-
- private void InitializeLogging()
- {
-#if DEBUG
- SerilogLogger.Initialize(new LoggerConfiguration()
- .MinimumLevel.Warning()
- .WriteTo.Trace(outputTemplate: "{Area}: {Message}")
- .CreateLogger());
-#endif
- }
- }
+ // No longer needed!
}
diff --git a/samples/XamlTestApplication/Program.cs b/samples/XamlTestApplication/Program.cs
index 76d1aa7efb..a6dc2a5501 100644
--- a/samples/XamlTestApplication/Program.cs
+++ b/samples/XamlTestApplication/Program.cs
@@ -1,39 +1,39 @@
// 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.Linq;
using System.Diagnostics;
using System.Windows.Threading;
using Perspex;
-using Perspex.Collections;
-using Perspex.Controls;
-using Perspex.Controls.Templates;
-using ReactiveUI;
-using XamlTestApplication.Views;
+using Serilog;
+using Perspex.Logging.Serilog;
namespace XamlTestApplication
{
internal class Program
{
- private static void Main()
+ private static void Main(string[] args)
{
- var sw = new Stopwatch();
- sw.Start();
-
+ // this sucks. Can we fix this? Do we even need it anymore?
var foo = Dispatcher.CurrentDispatcher;
- App application = new App
- {
-
- };
-
- var window = new MainWindow();
- window.Show();
+ InitializeLogging();
- sw.Stop();
- Debug.WriteLine($"Startup: {sw.ElapsedMilliseconds}ms");
+ new XamlTestApp()
+ .UseWin32()
+ .UseDirect2D()
+ .LoadFromXaml()
+ .RunWithMainWindow();
+ }
- Application.Current.Run(window);
+ private static void InitializeLogging()
+ {
+#if DEBUG
+ SerilogLogger.Initialize(new LoggerConfiguration()
+ .MinimumLevel.Warning()
+ .WriteTo.Trace(outputTemplate: "{Area}: {Message}")
+ .CreateLogger());
+#endif
}
}
}
\ No newline at end of file
diff --git a/samples/XamlTestApplicationPcl/XamlTestApp.cs b/samples/XamlTestApplicationPcl/XamlTestApp.cs
index a4d4ac2e0e..15f9ddb30e 100644
--- a/samples/XamlTestApplicationPcl/XamlTestApp.cs
+++ b/samples/XamlTestApplicationPcl/XamlTestApp.cs
@@ -1,23 +1,14 @@
using Perspex;
using Perspex.Markup.Xaml;
+using XamlTestApplication.Views;
namespace XamlTestApplication
{
- public abstract class XamlTestApp : Application
+ public class XamlTestApp : Application
{
- protected abstract void RegisterPlatform();
-
public XamlTestApp()
{
RegisterServices();
- RegisterPlatform();
- InitializeComponent();
- }
-
- private void InitializeComponent()
- {
- var loader = new PerspexXamlLoader();
- loader.Load(typeof(XamlTestApp), this);
}
}
}
diff --git a/src/Gtk/Perspex.Cairo/CairoPlatform.cs b/src/Gtk/Perspex.Cairo/CairoPlatform.cs
index 2c72811bbb..4e2c6727a5 100644
--- a/src/Gtk/Perspex.Cairo/CairoPlatform.cs
+++ b/src/Gtk/Perspex.Cairo/CairoPlatform.cs
@@ -7,6 +7,18 @@ using Perspex.Cairo.Media.Imaging;
using Perspex.Media;
using Perspex.Platform;
+namespace Perspex
+{
+ public static class GtkApplicationExtensions
+ {
+ public static TApp UseCairo(this TApp app) where TApp : Application
+ {
+ Perspex.Cairo.CairoPlatform.Initialize();
+ return app;
+ }
+ }
+}
+
namespace Perspex.Cairo
{
using System.IO;
diff --git a/src/Gtk/Perspex.Gtk/GtkPlatform.cs b/src/Gtk/Perspex.Gtk/GtkPlatform.cs
index b8a6d5c511..6a1d269dba 100644
--- a/src/Gtk/Perspex.Gtk/GtkPlatform.cs
+++ b/src/Gtk/Perspex.Gtk/GtkPlatform.cs
@@ -10,6 +10,18 @@ using Perspex.Input;
using Perspex.Platform;
using Perspex.Shared.PlatformSupport;
+namespace Perspex
+{
+ public static class GtkApplicationExtensions
+ {
+ public static TApp UseGtk(this TApp app) where TApp : Application
+ {
+ Perspex.Gtk.GtkPlatform.Initialize();
+ return app;
+ }
+ }
+}
+
namespace Perspex.Gtk
{
using Gtk = global::Gtk;
diff --git a/src/Markup/Perspex.Markup.Xaml/Data/Binding.cs b/src/Markup/Perspex.Markup.Xaml/Data/Binding.cs
index 588cc12f0e..a99582cea7 100644
--- a/src/Markup/Perspex.Markup.Xaml/Data/Binding.cs
+++ b/src/Markup/Perspex.Markup.Xaml/Data/Binding.cs
@@ -16,6 +16,22 @@ namespace Perspex.Markup.Xaml.Data
///
public class Binding : IBinding
{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public Binding()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The binding path.
+ public Binding(string path)
+ {
+ Path = path;
+ }
+
///
/// Gets or sets the to use.
///
diff --git a/src/Markup/Perspex.Markup.Xaml/PerspexXamlLoader.cs b/src/Markup/Perspex.Markup.Xaml/PerspexXamlLoader.cs
index 389e646215..68ae90d60f 100644
--- a/src/Markup/Perspex.Markup.Xaml/PerspexXamlLoader.cs
+++ b/src/Markup/Perspex.Markup.Xaml/PerspexXamlLoader.cs
@@ -187,3 +187,15 @@ namespace Perspex.Markup.Xaml
}
}
}
+
+namespace Perspex
+{
+ public static class XamlObjectExtensions
+ {
+ public static TObject LoadFromXaml(this TObject obj)
+ {
+ Markup.Xaml.PerspexXamlLoader.Load(obj);
+ return obj;
+ }
+ }
+}
diff --git a/src/Perspex.Controls/Control.cs b/src/Perspex.Controls/Control.cs
index 6ff38d08f1..74899a336a 100644
--- a/src/Perspex.Controls/Control.cs
+++ b/src/Perspex.Controls/Control.cs
@@ -337,19 +337,13 @@ namespace Perspex.Controls
IStyleHost IStyleHost.StylingParent => (IStyleHost)InheritanceParent;
///
- void ILogical.NotifyDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e)
- {
- this.OnDetachedFromLogicalTreeCore(e);
- }
-
- ///
- void ISupportInitialize.BeginInit()
+ public virtual void BeginInit()
{
++_initCount;
}
///
- void ISupportInitialize.EndInit()
+ public virtual void EndInit()
{
if (_initCount == 0)
{
@@ -373,14 +367,10 @@ namespace Perspex.Controls
}
}
- ///
- /// Gets a value which indicates whether a change to the is in
- /// the process of being notified.
- ///
- protected bool IsDataContextChanging
+ ///
+ void ILogical.NotifyDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e)
{
- get;
- private set;
+ this.OnDetachedFromLogicalTreeCore(e);
}
///
@@ -548,6 +538,21 @@ namespace Perspex.Controls
base.OnDetachedFromVisualTreeCore(e);
}
+ ///
+ /// Called before the property changes.
+ ///
+ protected virtual void OnDataContextChanging()
+ {
+ }
+
+ ///
+ /// Called after the property changes.
+ ///
+ protected virtual void OnDataContextChanged()
+ {
+ DataContextChanged?.Invoke(this, EventArgs.Empty);
+ }
+
///
protected override void OnGotFocus(GotFocusEventArgs e)
{
@@ -598,15 +603,6 @@ namespace Perspex.Controls
}
}
- ///
- /// Called when the is changed and all subscribers to that change
- /// have been notified.
- ///
- protected virtual void OnDataContextChanged()
- {
- DataContextChanged?.Invoke(this, EventArgs.Empty);
- }
-
///
/// Called when the property begins and ends being notified.
///
@@ -618,9 +614,11 @@ namespace Perspex.Controls
if (control != null)
{
- control.IsDataContextChanging = notifying;
-
- if (!notifying)
+ if (notifying)
+ {
+ control.OnDataContextChanging();
+ }
+ else
{
control.OnDataContextChanged();
}
diff --git a/src/Perspex.Controls/Presenters/ContentPresenter.cs b/src/Perspex.Controls/Presenters/ContentPresenter.cs
index f6a09f6cb1..0ea1eb4723 100644
--- a/src/Perspex.Controls/Presenters/ContentPresenter.cs
+++ b/src/Perspex.Controls/Presenters/ContentPresenter.cs
@@ -2,6 +2,7 @@
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
+using System.Reactive.Linq;
using Perspex.Controls.Primitives;
using Perspex.Controls.Templates;
using Perspex.Layout;
@@ -83,6 +84,17 @@ namespace Perspex.Controls.Presenters
TemplatedParentProperty.Changed.AddClassHandler(x => x.TemplatedParentChanged);
}
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public ContentPresenter()
+ {
+ var dataContext = this.GetObservable(ContentProperty)
+ .Select(x => x is IControl ? PerspexProperty.UnsetValue : x);
+
+ Bind(Control.DataContextProperty, dataContext);
+ }
+
///
/// Gets or sets a brush with which to paint the background.
///
diff --git a/src/Perspex.Controls/Primitives/SelectingItemsControl.cs b/src/Perspex.Controls/Primitives/SelectingItemsControl.cs
index 4d9482e7de..a141444754 100644
--- a/src/Perspex.Controls/Primitives/SelectingItemsControl.cs
+++ b/src/Perspex.Controls/Primitives/SelectingItemsControl.cs
@@ -107,7 +107,9 @@ namespace Perspex.Controls.Primitives
private IList _selectedItems;
private bool _ignoreContainerSelectionChanged;
private bool _syncingSelectedItems;
- private IList _clearSelectedItemsAfterDataContextChanged;
+ private int _updateCount;
+ private int _updateSelectedIndex;
+ private IList _updateSelectedItems;
///
/// Initializes static members of the class.
@@ -117,13 +119,6 @@ namespace Perspex.Controls.Primitives
IsSelectedChangedEvent.AddClassHandler(x => x.ContainerSelectionChanged);
}
- ///
- /// Initializes a new instance of the class.
- ///
- public SelectingItemsControl()
- {
- }
-
///
/// Occurs when the control's selection changes.
///
@@ -145,7 +140,6 @@ namespace Perspex.Controls.Primitives
///
/// Gets or sets the index of the selected item.
///
- [DependsOn(nameof(Items))]
public int SelectedIndex
{
get
@@ -155,14 +149,22 @@ namespace Perspex.Controls.Primitives
set
{
- var old = SelectedIndex;
- var effective = (value >= 0 && value < Items?.Cast
protected bool AlwaysSelected => (SelectionMode & SelectionMode.AlwaysSelected) != 0;
+ ///
+ public override void BeginInit()
+ {
+ base.BeginInit();
+ ++_updateCount;
+ _updateSelectedIndex = int.MinValue;
+ }
+
+ ///
+ public override void EndInit()
+ {
+ base.EndInit();
+
+ if (--_updateCount == 0)
+ {
+ UpdateFinished();
+ }
+ }
+
///
/// Tries to get the container that was the source of an event.
///
@@ -279,13 +299,16 @@ namespace Perspex.Controls.Primitives
{
base.ItemsChanged(e);
- if (SelectedIndex != -1)
- {
- SelectedIndex = IndexOf((IEnumerable)e.NewValue, SelectedItem);
- }
- else if (AlwaysSelected && Items != null && Items.Cast().Any())
+ if (_updateCount == 0)
{
- SelectedIndex = 0;
+ if (SelectedIndex != -1)
+ {
+ SelectedIndex = IndexOf((IEnumerable)e.NewValue, SelectedItem);
+ }
+ else if (AlwaysSelected && Items != null && Items.Cast().Any())
+ {
+ SelectedIndex = 0;
+ }
}
}
@@ -354,15 +377,22 @@ namespace Perspex.Controls.Primitives
}
}
+ ///
+ protected override void OnDataContextChanging()
+ {
+ base.OnDataContextChanging();
+ ++_updateCount;
+ }
+
///
protected override void OnDataContextChanged()
{
- if (_clearSelectedItemsAfterDataContextChanged == SelectedItems)
+ base.OnDataContextChanged();
+
+ if (--_updateCount == 0)
{
- _clearSelectedItemsAfterDataContextChanged.Clear();
+ UpdateFinished();
}
-
- _clearSelectedItemsAfterDataContextChanged = null;
}
///
@@ -695,6 +725,7 @@ namespace Perspex.Controls.Primitives
if (SelectedItems.Count > 0)
{
+ _selectedItem = null;
SelectedItemsAdded(SelectedItems);
added = SelectedItems;
}
@@ -800,5 +831,17 @@ namespace Perspex.Controls.Primitives
incc.CollectionChanged -= SelectedItemsCollectionChanged;
}
}
+
+ private void UpdateFinished()
+ {
+ if (_updateSelectedIndex != int.MinValue)
+ {
+ SelectedIndex = _updateSelectedIndex;
+ }
+ else if (_updateSelectedItems != null)
+ {
+ SelectedItems = _updateSelectedItems;
+ }
+ }
}
}
diff --git a/src/Perspex.Controls/Window.cs b/src/Perspex.Controls/Window.cs
index 7692f22e01..3a527ebb35 100644
--- a/src/Perspex.Controls/Window.cs
+++ b/src/Perspex.Controls/Window.cs
@@ -325,3 +325,16 @@ namespace Perspex.Controls
}
}
}
+
+namespace Perspex
+{
+ public static class WindowApplicationExtensions
+ {
+ public static void RunWithMainWindow(this Application app) where TWindow : Perspex.Controls.Window, new()
+ {
+ var window = new TWindow();
+ window.Show();
+ app.Run(window);
+ }
+ }
+}
diff --git a/src/Perspex.Diagnostics/DevTools.xaml.cs b/src/Perspex.Diagnostics/DevTools.xaml.cs
index a6e4e83533..5d4d962f15 100644
--- a/src/Perspex.Diagnostics/DevTools.xaml.cs
+++ b/src/Perspex.Diagnostics/DevTools.xaml.cs
@@ -13,9 +13,20 @@ using Perspex.Markup.Xaml;
using Perspex.VisualTree;
using ReactiveUI;
+namespace Perspex
+{
+ public static class WindowExtensions
+ {
+ public static void AttachDevTools(this Window window)
+ {
+ Perspex.Diagnostics.DevTools.Attach(window);
+ }
+ }
+}
+
namespace Perspex.Diagnostics
{
- public class DevTools : UserControl
+ public class DevTools : UserControl
{
private static Dictionary s_open = new Dictionary();
private IDisposable _keySubscription;
diff --git a/src/Perspex.Themes.Default/Button.xaml b/src/Perspex.Themes.Default/Button.xaml
index 93c372adc6..114849b131 100644
--- a/src/Perspex.Themes.Default/Button.xaml
+++ b/src/Perspex.Themes.Default/Button.xaml
@@ -14,7 +14,6 @@
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Content="{TemplateBinding Content}"
- DataContext="{TemplateBinding Content}"
Padding="{TemplateBinding Padding}"
TextBlock.Foreground="{TemplateBinding Foreground}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
diff --git a/src/Perspex.Themes.Default/CheckBox.xaml b/src/Perspex.Themes.Default/CheckBox.xaml
index 7452964213..d05e8b5cf6 100644
--- a/src/Perspex.Themes.Default/CheckBox.xaml
+++ b/src/Perspex.Themes.Default/CheckBox.xaml
@@ -22,7 +22,6 @@
diff --git a/src/Perspex.Themes.Default/ContentControl.xaml b/src/Perspex.Themes.Default/ContentControl.xaml
index cce99a45e6..90e34c7d3c 100644
--- a/src/Perspex.Themes.Default/ContentControl.xaml
+++ b/src/Perspex.Themes.Default/ContentControl.xaml
@@ -5,8 +5,7 @@
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
- Content="{TemplateBinding Content}"
- DataContext="{TemplateBinding Content}"
+ Content="{TemplateBinding Content}"
Padding="{TemplateBinding Padding}"/>
diff --git a/src/Perspex.Themes.Default/DropDown.xaml b/src/Perspex.Themes.Default/DropDown.xaml
index a0340099a5..37dd47d49a 100644
--- a/src/Perspex.Themes.Default/DropDown.xaml
+++ b/src/Perspex.Themes.Default/DropDown.xaml
@@ -11,7 +11,6 @@
BorderThickness="{TemplateBinding BorderThickness}">
diff --git a/src/Perspex.Themes.Default/DropDownItem.xaml b/src/Perspex.Themes.Default/DropDownItem.xaml
index 69742258a6..4900c961e4 100644
--- a/src/Perspex.Themes.Default/DropDownItem.xaml
+++ b/src/Perspex.Themes.Default/DropDownItem.xaml
@@ -10,7 +10,6 @@
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Content="{TemplateBinding Content}"
- DataContext="{TemplateBinding Content}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
Padding="{TemplateBinding Padding}"/>
diff --git a/src/Perspex.Themes.Default/Expander.xaml b/src/Perspex.Themes.Default/Expander.xaml
index 87728c555b..158f6514fd 100644
--- a/src/Perspex.Themes.Default/Expander.xaml
+++ b/src/Perspex.Themes.Default/Expander.xaml
@@ -17,7 +17,6 @@
Grid.Row="1"
IsVisible="{TemplateBinding IsExpanded}"
Content="{TemplateBinding Content}"
- DataContext="{TemplateBinding Content}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" />
@@ -35,7 +34,6 @@
Grid.Row="0"
IsVisible="{TemplateBinding IsExpanded}"
Content="{TemplateBinding Content}"
- DataContext="{TemplateBinding Content}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" />
@@ -53,7 +51,6 @@
Grid.Column="1"
IsVisible="{TemplateBinding IsExpanded}"
Content="{TemplateBinding Content}"
- DataContext="{TemplateBinding Content}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" />
@@ -71,7 +68,6 @@
Grid.Column="0"
IsVisible="{TemplateBinding IsExpanded}"
Content="{TemplateBinding Content}"
- DataContext="{TemplateBinding Content}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" />
diff --git a/src/Perspex.Themes.Default/LayoutTransformControl.xaml b/src/Perspex.Themes.Default/LayoutTransformControl.xaml
index 3d59fd4482..e393eedf83 100644
--- a/src/Perspex.Themes.Default/LayoutTransformControl.xaml
+++ b/src/Perspex.Themes.Default/LayoutTransformControl.xaml
@@ -6,7 +6,6 @@
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Content="{TemplateBinding Content}"
- DataContext="{TemplateBinding Content}"
Padding="{TemplateBinding Padding}"/>
diff --git a/src/Perspex.Themes.Default/ListBoxItem.xaml b/src/Perspex.Themes.Default/ListBoxItem.xaml
index 7c22cd4b47..784731d57b 100644
--- a/src/Perspex.Themes.Default/ListBoxItem.xaml
+++ b/src/Perspex.Themes.Default/ListBoxItem.xaml
@@ -7,7 +7,6 @@
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Content="{TemplateBinding Content}"
- DataContext="{TemplateBinding Content}"
Padding="{TemplateBinding Padding}"/>
diff --git a/src/Perspex.Themes.Default/MenuItem.xaml b/src/Perspex.Themes.Default/MenuItem.xaml
index 5b2fc5ec9e..2011bb041b 100644
--- a/src/Perspex.Themes.Default/MenuItem.xaml
+++ b/src/Perspex.Themes.Default/MenuItem.xaml
@@ -13,7 +13,6 @@
@@ -83,7 +81,6 @@
diff --git a/src/Perspex.Themes.Default/RadioButton.xaml b/src/Perspex.Themes.Default/RadioButton.xaml
index 6e5c958331..8fc0b14179 100644
--- a/src/Perspex.Themes.Default/RadioButton.xaml
+++ b/src/Perspex.Themes.Default/RadioButton.xaml
@@ -21,7 +21,6 @@
VerticalAlignment="Center"/>
diff --git a/src/Perspex.Themes.Default/TabStripItem.xaml b/src/Perspex.Themes.Default/TabStripItem.xaml
index 1ac77d6609..e32de4613b 100644
--- a/src/Perspex.Themes.Default/TabStripItem.xaml
+++ b/src/Perspex.Themes.Default/TabStripItem.xaml
@@ -9,7 +9,6 @@
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Content="{TemplateBinding Content}"
- DataContext="{TemplateBinding Content}"
Padding="{TemplateBinding Padding}"/>
diff --git a/src/Perspex.Themes.Default/ToggleButton.xaml b/src/Perspex.Themes.Default/ToggleButton.xaml
index 5f26051058..03354c9b27 100644
--- a/src/Perspex.Themes.Default/ToggleButton.xaml
+++ b/src/Perspex.Themes.Default/ToggleButton.xaml
@@ -14,7 +14,6 @@
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Content="{TemplateBinding Content}"
- DataContext="{TemplateBinding Content}"
Padding="{TemplateBinding Padding}"
TextBlock.Foreground="{TemplateBinding Foreground}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
diff --git a/src/Perspex.Themes.Default/ToolTip.xaml b/src/Perspex.Themes.Default/ToolTip.xaml
index 19af7c63bc..73bf2215ee 100644
--- a/src/Perspex.Themes.Default/ToolTip.xaml
+++ b/src/Perspex.Themes.Default/ToolTip.xaml
@@ -10,7 +10,6 @@
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Content="{TemplateBinding Content}"
- DataContext="{TemplateBinding Content}"
Padding="{TemplateBinding Padding}"/>
diff --git a/src/Perspex.Themes.Default/TreeViewItem.xaml b/src/Perspex.Themes.Default/TreeViewItem.xaml
index 072b5a0840..5e673d767f 100644
--- a/src/Perspex.Themes.Default/TreeViewItem.xaml
+++ b/src/Perspex.Themes.Default/TreeViewItem.xaml
@@ -13,7 +13,6 @@
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Content="{TemplateBinding Header}"
- DataContext="{TemplateBinding Header}"
Padding="{TemplateBinding Padding}"
TemplatedControl.IsTemplateFocusTarget="True"
Grid.Column="1"/>
diff --git a/src/Perspex.Themes.Default/Window.xaml b/src/Perspex.Themes.Default/Window.xaml
index 3dca88b9f4..4316626e58 100644
--- a/src/Perspex.Themes.Default/Window.xaml
+++ b/src/Perspex.Themes.Default/Window.xaml
@@ -6,10 +6,7 @@
-
+
diff --git a/src/Skia/Perspex.Skia/SkiaPlatform.cs b/src/Skia/Perspex.Skia/SkiaPlatform.cs
index 5526db720f..d9c5728a04 100644
--- a/src/Skia/Perspex.Skia/SkiaPlatform.cs
+++ b/src/Skia/Perspex.Skia/SkiaPlatform.cs
@@ -3,16 +3,26 @@ using System.Collections.Generic;
using System.Text;
using Perspex.Platform;
+namespace Perspex
+{
+ public static class SkiaApplicationExtensions
+ {
+ public static TApp UseSkia(this TApp app) where TApp : Application
+ {
+ Perspex.Skia.SkiaPlatform.Initialize();
+ return app;
+ }
+ }
+}
+
namespace Perspex.Skia
{
public static class SkiaPlatform
{
private static bool s_forceSoftwareRendering;
- public static void Initialize()
- {
- PerspexLocator.CurrentMutable.Bind().ToConstant(new PlatformRenderInterface());
- }
+ public static void Initialize()
+ => PerspexLocator.CurrentMutable.Bind().ToConstant(new PlatformRenderInterface());
public static bool ForceSoftwareRendering
{
diff --git a/src/Windows/Perspex.Direct2D1/Direct2D1Platform.cs b/src/Windows/Perspex.Direct2D1/Direct2D1Platform.cs
index 93c820b26d..fca41e0f64 100644
--- a/src/Windows/Perspex.Direct2D1/Direct2D1Platform.cs
+++ b/src/Windows/Perspex.Direct2D1/Direct2D1Platform.cs
@@ -7,6 +7,18 @@ using Perspex.Direct2D1.Media;
using Perspex.Media;
using Perspex.Platform;
+namespace Perspex
+{
+ public static class Direct2DApplicationExtensions
+ {
+ public static TApp UseDirect2D(this TApp app) where TApp : Application
+ {
+ Perspex.Direct2D1.Direct2D1Platform.Initialize();
+ return app;
+ }
+ }
+}
+
namespace Perspex.Direct2D1
{
public class Direct2D1Platform : IPlatformRenderInterface
diff --git a/src/Windows/Perspex.Direct2D1/Media/DrawingContext.cs b/src/Windows/Perspex.Direct2D1/Media/DrawingContext.cs
index 196588b5ad..e548989c1a 100644
--- a/src/Windows/Perspex.Direct2D1/Media/DrawingContext.cs
+++ b/src/Windows/Perspex.Direct2D1/Media/DrawingContext.cs
@@ -8,8 +8,8 @@ using System.Reactive.Disposables;
using Perspex.Media;
using SharpDX;
using SharpDX.Direct2D1;
-using IBitmap = Perspex.Media.Imaging.IBitmap;
using SharpDX.Mathematics.Interop;
+using IBitmap = Perspex.Media.Imaging.IBitmap;
namespace Perspex.Direct2D1.Media
{
diff --git a/src/Windows/Perspex.Direct2D1/Media/FormattedTextImpl.cs b/src/Windows/Perspex.Direct2D1/Media/FormattedTextImpl.cs
index 4daeb685fb..9c9bb6f29e 100644
--- a/src/Windows/Perspex.Direct2D1/Media/FormattedTextImpl.cs
+++ b/src/Windows/Perspex.Direct2D1/Media/FormattedTextImpl.cs
@@ -22,19 +22,20 @@ namespace Perspex.Direct2D1.Media
{
var factory = PerspexLocator.Current.GetService();
- var format = new DWrite.TextFormat(
+ using (var format = new DWrite.TextFormat(
factory,
fontFamily,
(DWrite.FontWeight)fontWeight,
(DWrite.FontStyle)fontStyle,
- (float)fontSize);
-
- TextLayout = new DWrite.TextLayout(
- factory,
- text ?? string.Empty,
- format,
- float.MaxValue,
- float.MaxValue);
+ (float)fontSize))
+ {
+ TextLayout = new DWrite.TextLayout(
+ factory,
+ text ?? string.Empty,
+ format,
+ float.MaxValue,
+ float.MaxValue);
+ }
TextLayout.TextAlignment = textAlignment.ToDirect2D();
}
diff --git a/src/Windows/Perspex.Direct2D1/Perspex.Direct2D1.csproj b/src/Windows/Perspex.Direct2D1/Perspex.Direct2D1.csproj
index dc1e582bf1..96653c4c23 100644
--- a/src/Windows/Perspex.Direct2D1/Perspex.Direct2D1.csproj
+++ b/src/Windows/Perspex.Direct2D1/Perspex.Direct2D1.csproj
@@ -36,27 +36,21 @@
CS1591
-
- ..\..\..\packages\SharpDX.3.0.1\lib\net45\SharpDX.dll
+
+ ..\..\..\packages\SharpDX.3.0.2\lib\net45\SharpDX.dll
True
-
- ..\..\..\packages\SharpDX.Direct2D1.3.0.1\lib\net45\SharpDX.Direct2D1.dll
+
+ ..\..\..\packages\SharpDX.Direct2D1.3.0.2\lib\net45\SharpDX.Direct2D1.dll
True
-
- ..\..\..\packages\SharpDX.DXGI.3.0.1\lib\net45\SharpDX.DXGI.dll
+
+ ..\..\..\packages\SharpDX.DXGI.3.0.2\lib\net45\SharpDX.DXGI.dll
True
-
-
-
-
-
-
..\..\..\packages\Rx-Core.2.2.5\lib\net45\System.Reactive.Core.dll
diff --git a/src/Windows/Perspex.Direct2D1/app.config b/src/Windows/Perspex.Direct2D1/app.config
index 0dfc66e74b..8a1277a9d4 100644
--- a/src/Windows/Perspex.Direct2D1/app.config
+++ b/src/Windows/Perspex.Direct2D1/app.config
@@ -15,16 +15,16 @@
-
-
+
+
-
-
+
+
-
-
+
+
diff --git a/src/Windows/Perspex.Direct2D1/packages.config b/src/Windows/Perspex.Direct2D1/packages.config
index b5795e1753..11c75cc603 100644
--- a/src/Windows/Perspex.Direct2D1/packages.config
+++ b/src/Windows/Perspex.Direct2D1/packages.config
@@ -3,7 +3,7 @@
-
-
-
+
+
+
\ No newline at end of file
diff --git a/src/Windows/Perspex.Win32/Perspex.Win32.csproj b/src/Windows/Perspex.Win32/Perspex.Win32.csproj
index 458e1de004..38968ea099 100644
--- a/src/Windows/Perspex.Win32/Perspex.Win32.csproj
+++ b/src/Windows/Perspex.Win32/Perspex.Win32.csproj
@@ -40,14 +40,8 @@
-
-
-
-
-
-
..\..\..\packages\Rx-Core.2.2.5\lib\net45\System.Reactive.Core.dll
diff --git a/src/Windows/Perspex.Win32/Win32Platform.cs b/src/Windows/Perspex.Win32/Win32Platform.cs
index 5fb0a7c4b7..480c7f859e 100644
--- a/src/Windows/Perspex.Win32/Win32Platform.cs
+++ b/src/Windows/Perspex.Win32/Win32Platform.cs
@@ -16,6 +16,18 @@ using Perspex.Shared.PlatformSupport;
using Perspex.Win32.Input;
using Perspex.Win32.Interop;
+namespace Perspex
+{
+ public static class Win32ApplicationExtensions
+ {
+ public static TApp UseWin32(this TApp app) where TApp : Application
+ {
+ Perspex.Win32.Win32Platform.Initialize();
+ return app;
+ }
+ }
+}
+
namespace Perspex.Win32
{
public class Win32Platform : IPlatformThreadingInterface, IPlatformSettings, IWindowingPlatform
diff --git a/tests/Perspex.Controls.UnitTests/Presenters/ContentPresenterTests.cs b/tests/Perspex.Controls.UnitTests/Presenters/ContentPresenterTests.cs
index b5c1b8f4eb..6ddb24afd1 100644
--- a/tests/Perspex.Controls.UnitTests/Presenters/ContentPresenterTests.cs
+++ b/tests/Perspex.Controls.UnitTests/Presenters/ContentPresenterTests.cs
@@ -130,6 +130,28 @@ namespace Perspex.Controls.UnitTests.Presenters
Assert.IsType(target.Child);
}
+ [Fact]
+ public void Assigning_Control_To_Content_Should_Not_Set_DataContext()
+ {
+ var target = new ContentPresenter
+ {
+ Content = new Border(),
+ };
+
+ Assert.False(target.IsSet(Control.DataContextProperty));
+ }
+
+ [Fact]
+ public void Assigning_NonControl_To_Content_Should_Set_DataContext()
+ {
+ var target = new ContentPresenter
+ {
+ Content = "foo",
+ };
+
+ Assert.Equal("foo", target.DataContext);
+ }
+
private class TestContentControl : TemplatedControl
{
public IControl Child { get; set; }
diff --git a/tests/Perspex.Controls.UnitTests/Primitives/SelectingItemsControlTests.cs b/tests/Perspex.Controls.UnitTests/Primitives/SelectingItemsControlTests.cs
index ab8a7090e7..f472740b5f 100644
--- a/tests/Perspex.Controls.UnitTests/Primitives/SelectingItemsControlTests.cs
+++ b/tests/Perspex.Controls.UnitTests/Primitives/SelectingItemsControlTests.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.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Perspex.Collections;
@@ -8,6 +9,8 @@ using Perspex.Controls.Presenters;
using Perspex.Controls.Primitives;
using Perspex.Controls.Templates;
using Perspex.Interactivity;
+using Perspex.Markup.Xaml.Data;
+using Perspex.UnitTests;
using Xunit;
namespace Perspex.Controls.UnitTests.Primitives
@@ -487,6 +490,86 @@ namespace Perspex.Controls.UnitTests.Primitives
Assert.True(called);
}
+ [Fact]
+ public void Order_Of_Setting_Items_And_SelectedIndex_During_Initialization_Should_Not_Matter()
+ {
+ var items = new[] { "Foo", "Bar" };
+ var target = new SelectingItemsControl();
+
+ ((ISupportInitialize)target).BeginInit();
+ target.SelectedIndex = 1;
+ target.Items = items;
+ ((ISupportInitialize)target).EndInit();
+
+ Assert.Equal(1, target.SelectedIndex);
+ Assert.Equal("Bar", target.SelectedItem);
+ }
+
+ [Fact]
+ public void Order_Of_Setting_Items_And_SelectedItem_During_Initialization_Should_Not_Matter()
+ {
+ var items = new[] { "Foo", "Bar" };
+ var target = new SelectingItemsControl();
+
+ ((ISupportInitialize)target).BeginInit();
+ target.SelectedItem = "Bar";
+ target.Items = items;
+ ((ISupportInitialize)target).EndInit();
+
+ Assert.Equal(1, target.SelectedIndex);
+ Assert.Equal("Bar", target.SelectedItem);
+ }
+
+ [Fact]
+ public void Changing_DataContext_Should_Not_Clear_Nested_ViewModel_SelectedItem()
+ {
+ var items = new[]
+ {
+ new Item(),
+ new Item(),
+ };
+
+ var vm = new MasterViewModel
+ {
+ Child = new ChildViewModel
+ {
+ Items = items,
+ SelectedItem = items[1],
+ }
+ };
+
+ var target = new SelectingItemsControl { DataContext = vm };
+ var itemsBinding = new Binding("Child.Items");
+ var selectedBinding = new Binding("Child.SelectedItem");
+
+ target.Bind(SelectingItemsControl.ItemsProperty, itemsBinding);
+ target.Bind(SelectingItemsControl.SelectedItemProperty, selectedBinding);
+
+ Assert.Equal(1, target.SelectedIndex);
+ Assert.Same(vm.Child.SelectedItem, target.SelectedItem);
+
+ items = new[]
+ {
+ new Item { Value = "Item1" },
+ new Item { Value = "Item2" },
+ new Item { Value = "Item3" },
+ };
+
+ vm = new MasterViewModel
+ {
+ Child = new ChildViewModel
+ {
+ Items = items,
+ SelectedItem = items[2],
+ }
+ };
+
+ target.DataContext = vm;
+
+ Assert.Equal(2, target.SelectedIndex);
+ Assert.Same(vm.Child.SelectedItem, target.SelectedItem);
+ }
+
private FuncControlTemplate Template()
{
return new FuncControlTemplate(control =>
@@ -500,7 +583,29 @@ namespace Perspex.Controls.UnitTests.Primitives
private class Item : Control, ISelectable
{
+ public string Value { get; set; }
public bool IsSelected { get; set; }
}
+
+ private class MasterViewModel : NotifyingBase
+ {
+ private ChildViewModel _child;
+
+ public ChildViewModel Child
+ {
+ get { return _child; }
+ set
+ {
+ _child = value;
+ RaisePropertyChanged();
+ }
+ }
+ }
+
+ private class ChildViewModel : NotifyingBase
+ {
+ public IList- Items { get; set; }
+ public Item SelectedItem { get; set; }
+ }
}
}
diff --git a/tests/Perspex.Controls.UnitTests/Primitives/SelectingItemsControlTests_Multiple.cs b/tests/Perspex.Controls.UnitTests/Primitives/SelectingItemsControlTests_Multiple.cs
index 21cce03055..89d1c4fb72 100644
--- a/tests/Perspex.Controls.UnitTests/Primitives/SelectingItemsControlTests_Multiple.cs
+++ b/tests/Perspex.Controls.UnitTests/Primitives/SelectingItemsControlTests_Multiple.cs
@@ -57,7 +57,7 @@ namespace Perspex.Controls.UnitTests.Primitives
};
target.ApplyTemplate();
- target.SelectedItems = new[] { "bar" };
+ target.SelectedItems = new PerspexList("bar");
Assert.Equal(1, target.SelectedIndex);
}
@@ -536,7 +536,7 @@ namespace Perspex.Controls.UnitTests.Primitives
target.ApplyTemplate();
target.Presenter.ApplyTemplate();
- target.SelectedItems = new[] { "foo", "baz" };
+ target.SelectedItems = new PerspexList("foo", "baz");
Assert.True(called);
}
diff --git a/tests/Perspex.Direct2D1.UnitTests/Perspex.Direct2D1.UnitTests.csproj b/tests/Perspex.Direct2D1.UnitTests/Perspex.Direct2D1.UnitTests.csproj
index 98197fbd8f..ca23b228fb 100644
--- a/tests/Perspex.Direct2D1.UnitTests/Perspex.Direct2D1.UnitTests.csproj
+++ b/tests/Perspex.Direct2D1.UnitTests/Perspex.Direct2D1.UnitTests.csproj
@@ -104,6 +104,7 @@
+
diff --git a/tests/Perspex.Direct2D1.UnitTests/app.config b/tests/Perspex.Direct2D1.UnitTests/app.config
new file mode 100644
index 0000000000..1723f9c94a
--- /dev/null
+++ b/tests/Perspex.Direct2D1.UnitTests/app.config
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/Perspex.Markup.Xaml.UnitTests/Xaml/BindingTests.cs b/tests/Perspex.Markup.Xaml.UnitTests/Xaml/BindingTests.cs
index 0224584cdb..7f01d3251f 100644
--- a/tests/Perspex.Markup.Xaml.UnitTests/Xaml/BindingTests.cs
+++ b/tests/Perspex.Markup.Xaml.UnitTests/Xaml/BindingTests.cs
@@ -16,8 +16,8 @@ namespace Perspex.Markup.Xaml.UnitTests.Xaml
{
var xaml = @"
+ xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
+ xmlns:local='clr-namespace:Perspex.Markup.Xaml.UnitTests.Xaml;assembly=Perspex.Markup.Xaml.UnitTests'>
";
var loader = new PerspexXamlLoader();
@@ -38,8 +38,8 @@ namespace Perspex.Markup.Xaml.UnitTests.Xaml
{
var xaml = @"
+ xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
+ xmlns:local='clr-namespace:Perspex.Markup.Xaml.UnitTests.Xaml;assembly=Perspex.Markup.Xaml.UnitTests'>