Browse Source

Merge branch 'master' into skiasharp

pull/506/head
Jason Jarvis 11 years ago
parent
commit
8e7b15a3a5
  1. 16
      samples/BindingTest/App.config
  2. 24
      samples/BindingTest/App.xaml.cs
  3. 5
      samples/BindingTest/MainWindow.xaml.cs
  4. 16
      samples/ControlCatalog/App.config
  5. 50
      samples/ControlCatalog/App.xaml.cs
  6. 1
      samples/ControlCatalog/ControlCatalog.csproj
  7. 7
      samples/ControlCatalog/MainWindow.xaml.cs
  8. 127
      samples/ControlCatalog/Program.cs
  9. 4
      samples/TestApplication/App.config
  10. 29
      samples/TestApplication/Program.cs
  11. 48
      samples/TestApplicationShared/App.cs
  12. 28
      samples/XamlTestApplication/App.config
  13. 23
      samples/XamlTestApplication/App.cs
  14. 40
      samples/XamlTestApplication/Program.cs
  15. 13
      samples/XamlTestApplicationPcl/XamlTestApp.cs
  16. 12
      src/Gtk/Perspex.Cairo/CairoPlatform.cs
  17. 12
      src/Gtk/Perspex.Gtk/GtkPlatform.cs
  18. 16
      src/Markup/Perspex.Markup.Xaml/Data/Binding.cs
  19. 12
      src/Markup/Perspex.Markup.Xaml/PerspexXamlLoader.cs
  20. 52
      src/Perspex.Controls/Control.cs
  21. 12
      src/Perspex.Controls/Presenters/ContentPresenter.cs
  22. 153
      src/Perspex.Controls/Primitives/SelectingItemsControl.cs
  23. 13
      src/Perspex.Controls/Window.cs
  24. 13
      src/Perspex.Diagnostics/DevTools.xaml.cs
  25. 1
      src/Perspex.Themes.Default/Button.xaml
  26. 1
      src/Perspex.Themes.Default/CheckBox.xaml
  27. 3
      src/Perspex.Themes.Default/ContentControl.xaml
  28. 1
      src/Perspex.Themes.Default/DropDown.xaml
  29. 1
      src/Perspex.Themes.Default/DropDownItem.xaml
  30. 4
      src/Perspex.Themes.Default/Expander.xaml
  31. 1
      src/Perspex.Themes.Default/LayoutTransformControl.xaml
  32. 1
      src/Perspex.Themes.Default/ListBoxItem.xaml
  33. 3
      src/Perspex.Themes.Default/MenuItem.xaml
  34. 1
      src/Perspex.Themes.Default/RadioButton.xaml
  35. 1
      src/Perspex.Themes.Default/TabStripItem.xaml
  36. 1
      src/Perspex.Themes.Default/ToggleButton.xaml
  37. 1
      src/Perspex.Themes.Default/ToolTip.xaml
  38. 1
      src/Perspex.Themes.Default/TreeViewItem.xaml
  39. 5
      src/Perspex.Themes.Default/Window.xaml
  40. 18
      src/Skia/Perspex.Skia/SkiaPlatform.cs
  41. 12
      src/Windows/Perspex.Direct2D1/Direct2D1Platform.cs
  42. 2
      src/Windows/Perspex.Direct2D1/Media/DrawingContext.cs
  43. 19
      src/Windows/Perspex.Direct2D1/Media/FormattedTextImpl.cs
  44. 18
      src/Windows/Perspex.Direct2D1/Perspex.Direct2D1.csproj
  45. 12
      src/Windows/Perspex.Direct2D1/app.config
  46. 6
      src/Windows/Perspex.Direct2D1/packages.config
  47. 6
      src/Windows/Perspex.Win32/Perspex.Win32.csproj
  48. 12
      src/Windows/Perspex.Win32/Win32Platform.cs
  49. 22
      tests/Perspex.Controls.UnitTests/Presenters/ContentPresenterTests.cs
  50. 105
      tests/Perspex.Controls.UnitTests/Primitives/SelectingItemsControlTests.cs
  51. 4
      tests/Perspex.Controls.UnitTests/Primitives/SelectingItemsControlTests_Multiple.cs
  52. 1
      tests/Perspex.Direct2D1.UnitTests/Perspex.Direct2D1.UnitTests.csproj
  53. 15
      tests/Perspex.Direct2D1.UnitTests/app.config
  54. 41
      tests/Perspex.Markup.Xaml.UnitTests/Xaml/BindingTests.cs
  55. 4
      tests/Perspex.RenderTests/app.config

16
samples/BindingTest/App.config

@ -1,6 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="SharpDX" publicKeyToken="b4dcf0f35e5521f1" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.2.0" newVersion="3.0.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="SharpDX.DXGI" publicKeyToken="b4dcf0f35e5521f1" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.2.0" newVersion="3.0.2.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

24
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<MainWindow>();
}
private void InitializeLogging()
private static void InitializeLogging()
{
#if DEBUG
SerilogLogger.Initialize(new LoggerConfiguration()

5
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();
}
}
}

16
samples/ControlCatalog/App.config

@ -1,13 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Mono.Cairo" publicKeyToken="0738eb9f132ed756" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0"/>
<assemblyIdentity name="Mono.Cairo" publicKeyToken="0738eb9f132ed756" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="SharpDX" publicKeyToken="b4dcf0f35e5521f1" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.2.0" newVersion="3.0.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="SharpDX.DXGI" publicKeyToken="b4dcf0f35e5521f1" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.2.0" newVersion="3.0.2.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>

50
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;
}
}
}
}

1
samples/ControlCatalog/ControlCatalog.csproj

@ -103,6 +103,7 @@
<Compile Include="Pages\SliderPage.xaml.cs">
<DependentUpon>SliderPage.xaml</DependentUpon>
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>

7
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();
}
}
}

127
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<MainWindow>();
}
// 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
};
/// <summary>
/// Default (Optimal) render system for a particular platform
/// </summary>
/// <returns></returns>
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;
}
/// <summary>
/// Returns an array of avalidable rendering systems in priority order
/// </summary>
/// <returns></returns>
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];
}
/// <summary>
/// Selects the optimal render system for desktop platforms. Supports cmd line overrides
/// </summary>
/// <param name="app"></param>
/// <param name="args"></param>
public static TApp ConfigureRenderSystem<TApp>(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;
}
}
}

4
samples/TestApplication/App.config

@ -23,11 +23,11 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="SharpDX" publicKeyToken="b4dcf0f35e5521f1" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
<bindingRedirect oldVersion="0.0.0.0-3.0.2.0" newVersion="3.0.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="SharpDX.DXGI" publicKeyToken="b4dcf0f35e5521f1" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
<bindingRedirect oldVersion="0.0.0.0-3.0.2.0" newVersion="3.0.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Mono.Cairo" publicKeyToken="0738eb9f132ed756" culture="neutral" />

29
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();
}
}
}

48
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<Node>(
x => new TextBlock {Text = x.Name},
x => x.Children),
};
}
Styles.Add(new SampleTabStyle());
DataTemplates = new DataTemplates
{
new FuncTreeDataTemplate<Node>(
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);
}
}
}

28
samples/XamlTestApplication/App.config

@ -1,33 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Reactive.Interfaces" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-2.2.5.0" newVersion="2.2.5.0"/>
<assemblyIdentity name="System.Reactive.Interfaces" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.2.5.0" newVersion="2.2.5.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Reactive.Core" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-2.2.5.0" newVersion="2.2.5.0"/>
<assemblyIdentity name="System.Reactive.Core" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.2.5.0" newVersion="2.2.5.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Reactive.Linq" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-2.2.5.0" newVersion="2.2.5.0"/>
<assemblyIdentity name="System.Reactive.Linq" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.2.5.0" newVersion="2.2.5.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="SharpDX.Direct2D1" publicKeyToken="b4dcf0f35e5521f1" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0"/>
<assemblyIdentity name="SharpDX.Direct2D1" publicKeyToken="b4dcf0f35e5521f1" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="SharpDX" publicKeyToken="b4dcf0f35e5521f1" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0"/>
<assemblyIdentity name="SharpDX" publicKeyToken="b4dcf0f35e5521f1" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.2.0" newVersion="3.0.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="SharpDX.DXGI" publicKeyToken="b4dcf0f35e5521f1" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0"/>
<assemblyIdentity name="SharpDX.DXGI" publicKeyToken="b4dcf0f35e5521f1" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.2.0" newVersion="3.0.2.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>

23
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!
}

40
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<Views.MainWindow>();
}
Application.Current.Run(window);
private static void InitializeLogging()
{
#if DEBUG
SerilogLogger.Initialize(new LoggerConfiguration()
.MinimumLevel.Warning()
.WriteTo.Trace(outputTemplate: "{Area}: {Message}")
.CreateLogger());
#endif
}
}
}

13
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);
}
}
}

12
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<TApp>(this TApp app) where TApp : Application
{
Perspex.Cairo.CairoPlatform.Initialize();
return app;
}
}
}
namespace Perspex.Cairo
{
using System.IO;

12
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<TApp>(this TApp app) where TApp : Application
{
Perspex.Gtk.GtkPlatform.Initialize();
return app;
}
}
}
namespace Perspex.Gtk
{
using Gtk = global::Gtk;

16
src/Markup/Perspex.Markup.Xaml/Data/Binding.cs

@ -16,6 +16,22 @@ namespace Perspex.Markup.Xaml.Data
/// </summary>
public class Binding : IBinding
{
/// <summary>
/// Initializes a new instance of the <see cref="Binding"/> class.
/// </summary>
public Binding()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="Binding"/> class.
/// </summary>
/// <param name="path">The binding path.</param>
public Binding(string path)
{
Path = path;
}
/// <summary>
/// Gets or sets the <see cref="IValueConverter"/> to use.
/// </summary>

12
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<TObject>(this TObject obj)
{
Markup.Xaml.PerspexXamlLoader.Load(obj);
return obj;
}
}
}

52
src/Perspex.Controls/Control.cs

@ -337,19 +337,13 @@ namespace Perspex.Controls
IStyleHost IStyleHost.StylingParent => (IStyleHost)InheritanceParent;
/// <inheritdoc/>
void ILogical.NotifyDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e)
{
this.OnDetachedFromLogicalTreeCore(e);
}
/// <inheritdoc/>
void ISupportInitialize.BeginInit()
public virtual void BeginInit()
{
++_initCount;
}
/// <inheritdoc/>
void ISupportInitialize.EndInit()
public virtual void EndInit()
{
if (_initCount == 0)
{
@ -373,14 +367,10 @@ namespace Perspex.Controls
}
}
/// <summary>
/// Gets a value which indicates whether a change to the <see cref="DataContext"/> is in
/// the process of being notified.
/// </summary>
protected bool IsDataContextChanging
/// <inheritdoc/>
void ILogical.NotifyDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e)
{
get;
private set;
this.OnDetachedFromLogicalTreeCore(e);
}
/// <summary>
@ -548,6 +538,21 @@ namespace Perspex.Controls
base.OnDetachedFromVisualTreeCore(e);
}
/// <summary>
/// Called before the <see cref="DataContext"/> property changes.
/// </summary>
protected virtual void OnDataContextChanging()
{
}
/// <summary>
/// Called after the <see cref="DataContext"/> property changes.
/// </summary>
protected virtual void OnDataContextChanged()
{
DataContextChanged?.Invoke(this, EventArgs.Empty);
}
/// <inheritdoc/>
protected override void OnGotFocus(GotFocusEventArgs e)
{
@ -598,15 +603,6 @@ namespace Perspex.Controls
}
}
/// <summary>
/// Called when the <see cref="DataContext"/> is changed and all subscribers to that change
/// have been notified.
/// </summary>
protected virtual void OnDataContextChanged()
{
DataContextChanged?.Invoke(this, EventArgs.Empty);
}
/// <summary>
/// Called when the <see cref="DataContext"/> property begins and ends being notified.
/// </summary>
@ -618,9 +614,11 @@ namespace Perspex.Controls
if (control != null)
{
control.IsDataContextChanging = notifying;
if (!notifying)
if (notifying)
{
control.OnDataContextChanging();
}
else
{
control.OnDataContextChanged();
}

12
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<ContentPresenter>(x => x.TemplatedParentChanged);
}
/// <summary>
/// Initializes a new instance of the <see cref="ContentPresenter"/> class.
/// </summary>
public ContentPresenter()
{
var dataContext = this.GetObservable(ContentProperty)
.Select(x => x is IControl ? PerspexProperty.UnsetValue : x);
Bind(Control.DataContextProperty, dataContext);
}
/// <summary>
/// Gets or sets a brush with which to paint the background.
/// </summary>

153
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;
/// <summary>
/// Initializes static members of the <see cref="SelectingItemsControl"/> class.
@ -117,13 +119,6 @@ namespace Perspex.Controls.Primitives
IsSelectedChangedEvent.AddClassHandler<SelectingItemsControl>(x => x.ContainerSelectionChanged);
}
/// <summary>
/// Initializes a new instance of the <see cref="SelectingItemsControl"/> class.
/// </summary>
public SelectingItemsControl()
{
}
/// <summary>
/// Occurs when the control's selection changes.
/// </summary>
@ -145,7 +140,6 @@ namespace Perspex.Controls.Primitives
/// <summary>
/// Gets or sets the index of the selected item.
/// </summary>
[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<object>().Count()) ? value : -1;
if (_updateCount == 0)
{
var old = SelectedIndex;
var effective = (value >= 0 && value < Items?.Cast<object>().Count()) ? value : -1;
if (old != effective)
if (old != effective)
{
_selectedIndex = effective;
RaisePropertyChanged(SelectedIndexProperty, old, effective, BindingPriority.LocalValue);
SelectedItem = ElementAt(Items, effective);
}
}
else
{
_selectedIndex = effective;
RaisePropertyChanged(SelectedIndexProperty, old, effective, BindingPriority.LocalValue);
SelectedItem = ElementAt(Items, effective);
_updateSelectedIndex = value;
_updateSelectedItems = null;
}
}
}
@ -170,7 +172,6 @@ namespace Perspex.Controls.Primitives
/// <summary>
/// Gets or sets the selected item.
/// </summary>
[DependsOn(nameof(Items))]
public object SelectedItem
{
get
@ -180,45 +181,39 @@ namespace Perspex.Controls.Primitives
set
{
var old = SelectedItem;
var index = IndexOf(Items, value);
var effective = index != -1 ? value : null;
if (!object.Equals(effective, old))
if (_updateCount == 0)
{
_selectedItem = effective;
RaisePropertyChanged(SelectedItemProperty, old, effective, BindingPriority.LocalValue);
SelectedIndex = index;
var old = SelectedItem;
var index = IndexOf(Items, value);
var effective = index != -1 ? value : null;
if (effective != null)
if (!object.Equals(effective, old))
{
if (SelectedItems.Count != 1 || SelectedItems[0] != effective)
_selectedItem = effective;
RaisePropertyChanged(SelectedItemProperty, old, effective, BindingPriority.LocalValue);
SelectedIndex = index;
if (effective != null)
{
_syncingSelectedItems = true;
SelectedItems.Clear();
SelectedItems.Add(effective);
_syncingSelectedItems = false;
if (SelectedItems.Count != 1 || SelectedItems[0] != effective)
{
_syncingSelectedItems = true;
SelectedItems.Clear();
SelectedItems.Add(effective);
_syncingSelectedItems = false;
}
}
}
else if (SelectedItems.Count > 0)
{
if (!IsDataContextChanging)
else if (SelectedItems.Count > 0)
{
SelectedItems.Clear();
}
else
{
// The DataContext is changing, and it's quite possible that our
// selection is being cleared because both Items and SelectedItems
// are bound to something on the DataContext. However, if we clear
// the collection now, we may be clearing a the SelectedItems from
// the DataContext which is being unbound, so do it after DataContext
// has notified all interested parties, in
// the OnDataContextFinishedChanging method.
_clearSelectedItemsAfterDataContextChanged = SelectedItems;
}
}
}
else
{
_updateSelectedItems = new PerspexList<object>(value);
_updateSelectedIndex = int.MinValue;
}
}
}
@ -240,6 +235,12 @@ namespace Perspex.Controls.Primitives
set
{
if (value?.IsFixedSize == true || value?.IsReadOnly == true)
{
throw new NotSupportedException(
"Cannot use a fixed size or read-only collection as SelectedItems.");
}
UnsubscribeFromSelectedItems();
_selectedItems = value ?? new PerspexList<object>();
SubscribeToSelectedItems();
@ -260,6 +261,25 @@ namespace Perspex.Controls.Primitives
/// </summary>
protected bool AlwaysSelected => (SelectionMode & SelectionMode.AlwaysSelected) != 0;
/// <inheritdoc/>
public override void BeginInit()
{
base.BeginInit();
++_updateCount;
_updateSelectedIndex = int.MinValue;
}
/// <inheritdoc/>
public override void EndInit()
{
base.EndInit();
if (--_updateCount == 0)
{
UpdateFinished();
}
}
/// <summary>
/// Tries to get the container that was the source of an event.
/// </summary>
@ -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<object>().Any())
if (_updateCount == 0)
{
SelectedIndex = 0;
if (SelectedIndex != -1)
{
SelectedIndex = IndexOf((IEnumerable)e.NewValue, SelectedItem);
}
else if (AlwaysSelected && Items != null && Items.Cast<object>().Any())
{
SelectedIndex = 0;
}
}
}
@ -354,15 +377,22 @@ namespace Perspex.Controls.Primitives
}
}
/// <inheritdoc/>
protected override void OnDataContextChanging()
{
base.OnDataContextChanging();
++_updateCount;
}
/// <inheritdoc/>
protected override void OnDataContextChanged()
{
if (_clearSelectedItemsAfterDataContextChanged == SelectedItems)
base.OnDataContextChanged();
if (--_updateCount == 0)
{
_clearSelectedItemsAfterDataContextChanged.Clear();
UpdateFinished();
}
_clearSelectedItemsAfterDataContextChanged = null;
}
/// <summary>
@ -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;
}
}
}
}

13
src/Perspex.Controls/Window.cs

@ -325,3 +325,16 @@ namespace Perspex.Controls
}
}
}
namespace Perspex
{
public static class WindowApplicationExtensions
{
public static void RunWithMainWindow<TWindow>(this Application app) where TWindow : Perspex.Controls.Window, new()
{
var window = new TWindow();
window.Show();
app.Run(window);
}
}
}

13
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<Window, Window> s_open = new Dictionary<Window, Window>();
private IDisposable _keySubscription;

1
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}"

1
src/Perspex.Themes.Default/CheckBox.xaml

@ -22,7 +22,6 @@
</Border>
<ContentPresenter Name="PART_ContentPresenter"
Content="{TemplateBinding Content}"
DataContext="{TemplateBinding Content}"
Margin="4,0,0,0"
VerticalAlignment="Center"
Grid.Column="1"/>

3
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}"/>
</ControlTemplate>
</Setter>

1
src/Perspex.Themes.Default/DropDown.xaml

@ -11,7 +11,6 @@
BorderThickness="{TemplateBinding BorderThickness}">
<Grid ColumnDefinitions="*,Auto">
<ContentPresenter Content="{TemplateBinding SelectionBoxItem}"
DataContext="{TemplateBinding SelectionBoxItem}"
Margin="{TemplateBinding Padding}"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>

1
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}"/>

4
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" />
</Grid>
@ -35,7 +34,6 @@
Grid.Row="0"
IsVisible="{TemplateBinding IsExpanded}"
Content="{TemplateBinding Content}"
DataContext="{TemplateBinding Content}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" />
</Grid>
@ -53,7 +51,6 @@
Grid.Column="1"
IsVisible="{TemplateBinding IsExpanded}"
Content="{TemplateBinding Content}"
DataContext="{TemplateBinding Content}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" />
</Grid>
@ -71,7 +68,6 @@
Grid.Column="0"
IsVisible="{TemplateBinding IsExpanded}"
Content="{TemplateBinding Content}"
DataContext="{TemplateBinding Content}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" />
</Grid>

1
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}"/>
</ControlTemplate>
</Setter>

1
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}"/>
</ControlTemplate>
</Setter>

3
src/Perspex.Themes.Default/MenuItem.xaml

@ -13,7 +13,6 @@
<Grid ColumnDefinitions="22,13,*,20">
<ContentPresenter Name="icon"
Content="{TemplateBinding Icon}"
DataContext="{TemplateBinding Icon}"
Width="16"
Height="16"
Margin="3"
@ -27,7 +26,6 @@
VerticalAlignment="Center"/>
<ContentPresenter Name="PART_HeaderPresenter"
Content="{TemplateBinding Header}"
DataContext="{TemplateBinding Header}"
Margin="{TemplateBinding Padding}"
VerticalAlignment="Center"
Grid.Column="2">
@ -83,7 +81,6 @@
<Panel>
<ContentPresenter Name="PART_HeaderPresenter"
Content="{TemplateBinding Header}"
DataContext="{TemplateBinding Header}"
Margin="{TemplateBinding Padding}">
<ContentPresenter.DataTemplates>
<DataTemplate DataType="sys:String">

1
src/Perspex.Themes.Default/RadioButton.xaml

@ -21,7 +21,6 @@
VerticalAlignment="Center"/>
<ContentPresenter Name="PART_ContentPresenter"
Content="{TemplateBinding Content}"
DataContext="{TemplateBinding Content}"
Margin="4,0,0,0"
VerticalAlignment="Center"
Grid.Column="1"/>

1
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}"/>
</ControlTemplate>
</Setter>

1
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}"

1
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}"/>
</ControlTemplate>
</Setter>

1
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"/>

5
src/Perspex.Themes.Default/Window.xaml

@ -6,10 +6,7 @@
<ControlTemplate>
<Border Background="{TemplateBinding Background}">
<AdornerDecorator>
<ContentPresenter Name="PART_ContentPresenter"
Content="{TemplateBinding Content}"
DataContext="{TemplateBinding Content}"
Margin="{TemplateBinding Padding}"/>
<ContentPresenter Name="PART_ContentPresenter" Content="{TemplateBinding Content}" Margin="{TemplateBinding Padding}"/>
</AdornerDecorator>
</Border>
</ControlTemplate>

18
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<TApp>(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<IPlatformRenderInterface>().ToConstant(new PlatformRenderInterface());
}
public static void Initialize()
=> PerspexLocator.CurrentMutable.Bind<IPlatformRenderInterface>().ToConstant(new PlatformRenderInterface());
public static bool ForceSoftwareRendering
{

12
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<TApp>(this TApp app) where TApp : Application
{
Perspex.Direct2D1.Direct2D1Platform.Initialize();
return app;
}
}
}
namespace Perspex.Direct2D1
{
public class Direct2D1Platform : IPlatformRenderInterface

2
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
{

19
src/Windows/Perspex.Direct2D1/Media/FormattedTextImpl.cs

@ -22,19 +22,20 @@ namespace Perspex.Direct2D1.Media
{
var factory = PerspexLocator.Current.GetService<DWrite.Factory>();
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();
}

18
src/Windows/Perspex.Direct2D1/Perspex.Direct2D1.csproj

@ -36,27 +36,21 @@
<NoWarn>CS1591</NoWarn>
</PropertyGroup>
<ItemGroup>
<Reference Include="SharpDX, Version=3.0.1.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\SharpDX.3.0.1\lib\net45\SharpDX.dll</HintPath>
<Reference Include="SharpDX, Version=3.0.2.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\SharpDX.3.0.2\lib\net45\SharpDX.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="SharpDX.Direct2D1, Version=3.0.1.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\SharpDX.Direct2D1.3.0.1\lib\net45\SharpDX.Direct2D1.dll</HintPath>
<Reference Include="SharpDX.Direct2D1, Version=3.0.2.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\SharpDX.Direct2D1.3.0.2\lib\net45\SharpDX.Direct2D1.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="SharpDX.DXGI, Version=3.0.1.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\SharpDX.DXGI.3.0.1\lib\net45\SharpDX.DXGI.dll</HintPath>
<Reference Include="SharpDX.DXGI, Version=3.0.2.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\SharpDX.DXGI.3.0.2\lib\net45\SharpDX.DXGI.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="System.Reactive.Core">
<HintPath>..\..\..\packages\Rx-Core.2.2.5\lib\net45\System.Reactive.Core.dll</HintPath>
</Reference>

12
src/Windows/Perspex.Direct2D1/app.config

@ -15,16 +15,16 @@
<bindingRedirect oldVersion="0.0.0.0-2.1.30214.0" newVersion="2.1.30214.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="SharpDX.Direct2D1" publicKeyToken="b4dcf0f35e5521f1" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0"/>
<assemblyIdentity name="SharpDX.Direct2D1" publicKeyToken="b4dcf0f35e5521f1" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="SharpDX" publicKeyToken="b4dcf0f35e5521f1" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0"/>
<assemblyIdentity name="SharpDX" publicKeyToken="b4dcf0f35e5521f1" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.2.0" newVersion="3.0.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="SharpDX.DXGI" publicKeyToken="b4dcf0f35e5521f1" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0"/>
<assemblyIdentity name="SharpDX.DXGI" publicKeyToken="b4dcf0f35e5521f1" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.2.0" newVersion="3.0.2.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>

6
src/Windows/Perspex.Direct2D1/packages.config

@ -3,7 +3,7 @@
<package id="Rx-Core" version="2.2.5" targetFramework="net45" />
<package id="Rx-Interfaces" version="2.2.5" targetFramework="net45" />
<package id="Rx-PlatformServices" version="2.2.5" targetFramework="net45" />
<package id="SharpDX" version="3.0.1" targetFramework="net45" />
<package id="SharpDX.Direct2D1" version="3.0.1" targetFramework="net45" />
<package id="SharpDX.DXGI" version="3.0.1" targetFramework="net45" />
<package id="SharpDX" version="3.0.2" targetFramework="net45" />
<package id="SharpDX.Direct2D1" version="3.0.2" targetFramework="net45" />
<package id="SharpDX.DXGI" version="3.0.2" targetFramework="net45" />
</packages>

6
src/Windows/Perspex.Win32/Perspex.Win32.csproj

@ -40,14 +40,8 @@
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xaml" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="System.Reactive.Core">
<HintPath>..\..\..\packages\Rx-Core.2.2.5\lib\net45\System.Reactive.Core.dll</HintPath>
</Reference>

12
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<TApp>(this TApp app) where TApp : Application
{
Perspex.Win32.Win32Platform.Initialize();
return app;
}
}
}
namespace Perspex.Win32
{
public class Win32Platform : IPlatformThreadingInterface, IPlatformSettings, IWindowingPlatform

22
tests/Perspex.Controls.UnitTests/Presenters/ContentPresenterTests.cs

@ -130,6 +130,28 @@ namespace Perspex.Controls.UnitTests.Presenters
Assert.IsType<Decorator>(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; }

105
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<SelectingItemsControl>(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<Item> Items { get; set; }
public Item SelectedItem { get; set; }
}
}
}

4
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<object>("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<object>("foo", "baz");
Assert.True(called);
}

1
tests/Perspex.Direct2D1.UnitTests/Perspex.Direct2D1.UnitTests.csproj

@ -104,6 +104,7 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>

15
tests/Perspex.Direct2D1.UnitTests/app.config

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="SharpDX" publicKeyToken="b4dcf0f35e5521f1" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.2.0" newVersion="3.0.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="SharpDX.DXGI" publicKeyToken="b4dcf0f35e5521f1" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.2.0" newVersion="3.0.2.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

41
tests/Perspex.Markup.Xaml.UnitTests/Xaml/BindingTests.cs

@ -16,8 +16,8 @@ namespace Perspex.Markup.Xaml.UnitTests.Xaml
{
var xaml = @"
<Window xmlns='https://github.com/perspex'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
xmlns:local='clr-namespace:Perspex.Markup.Xaml.UnitTests.Xaml;assembly=Perspex.Markup.Xaml.UnitTests'>
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
xmlns:local='clr-namespace:Perspex.Markup.Xaml.UnitTests.Xaml;assembly=Perspex.Markup.Xaml.UnitTests'>
<Button Name='button' Content='{Binding Foo}'/>
</Window>";
var loader = new PerspexXamlLoader();
@ -38,8 +38,8 @@ namespace Perspex.Markup.Xaml.UnitTests.Xaml
{
var xaml = @"
<Window xmlns='https://github.com/perspex'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
xmlns:local='clr-namespace:Perspex.Markup.Xaml.UnitTests.Xaml;assembly=Perspex.Markup.Xaml.UnitTests'>
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
xmlns:local='clr-namespace:Perspex.Markup.Xaml.UnitTests.Xaml;assembly=Perspex.Markup.Xaml.UnitTests'>
<Button Name='button'>
<Button.Content>
<Binding Path='Foo'/>
@ -64,8 +64,8 @@ namespace Perspex.Markup.Xaml.UnitTests.Xaml
{
var xaml = @"
<Window xmlns='https://github.com/perspex'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
xmlns:local='clr-namespace:Perspex.Markup.Xaml.UnitTests.Xaml;assembly=Perspex.Markup.Xaml.UnitTests'>
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
xmlns:local='clr-namespace:Perspex.Markup.Xaml.UnitTests.Xaml;assembly=Perspex.Markup.Xaml.UnitTests'>
<Button Name='button' Content='Foo'>
<Button.Tag>
<local:NonControl Control='{Binding #button}'/>
@ -87,8 +87,8 @@ namespace Perspex.Markup.Xaml.UnitTests.Xaml
{
var xaml = @"
<Window xmlns='https://github.com/perspex'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
xmlns:local='clr-namespace:Perspex.Markup.Xaml.UnitTests.Xaml;assembly=Perspex.Markup.Xaml.UnitTests'>
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
xmlns:local='clr-namespace:Perspex.Markup.Xaml.UnitTests.Xaml;assembly=Perspex.Markup.Xaml.UnitTests'>
<Button Name='button'>
<Button.Tag>
<local:NonControl String='{Binding Foo}'/>
@ -112,8 +112,8 @@ namespace Perspex.Markup.Xaml.UnitTests.Xaml
{
var xaml = @"
<Window xmlns='https://github.com/perspex'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
Title='{Binding Foo}'>
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
Title='{Binding Foo}'>
</Window>";
var loader = new PerspexXamlLoader();
var window = (Window)loader.Load(xaml);
@ -124,5 +124,26 @@ namespace Perspex.Markup.Xaml.UnitTests.Xaml
Assert.Equal("foo", window.Title);
}
}
[Fact]
public void Binding_DataContext_To_Inherited_DataContext_Works()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var xaml = @"
<Window xmlns='https://github.com/perspex'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
<Border DataContext='{Binding Foo}'/>
</Window>";
var loader = new PerspexXamlLoader();
var window = (Window)loader.Load(xaml);
var border = (Border)window.Content;
window.DataContext = new { Foo = "foo" };
window.ApplyTemplate();
Assert.Equal("foo", border.DataContext);
}
}
}
}

4
tests/Perspex.RenderTests/app.config

@ -20,11 +20,11 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="SharpDX" publicKeyToken="b4dcf0f35e5521f1" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
<bindingRedirect oldVersion="0.0.0.0-3.0.2.0" newVersion="3.0.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="SharpDX.DXGI" publicKeyToken="b4dcf0f35e5521f1" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
<bindingRedirect oldVersion="0.0.0.0-3.0.2.0" newVersion="3.0.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Mono.Cairo" publicKeyToken="0738eb9f132ed756" culture="neutral" />

Loading…
Cancel
Save