Visual Studio 2015 allows easily combine OpenGL graphics with XAML controls in a single window. To accomplish this task we can create a new project based on “XAML App for OpenGL ES (Universal Windows)” template:
Compiling MSOpenTech ANGLE project
ANGLE is a wrapper library that implements OpenGL ES API (version 2.0 and parts of 3.0) and translates OpenGL ES calls to their DirectX equivalents. See https://github.com/MSOpenTech/angle for more information.
There are two options how to use ANGLE: install its binaries as a NuGet package or compile it from the source code. I believe that cool software developers, like real heroes, never search easy ways, so I decided to compile ANGLE from the source code with VS2015 Community.
First I cloned the repository and ensured that my branch is ms-master:
Synchronization mechanism in DirectX/XAML UWP application
Probably it would be better if I learned Java 15 years ago because Java technologies do not change so rapidly, but I love C++ very much and I spent some time investigating how the application based on DirectX 11 and XAML Visual Studio 2015 template works on relatively new UWP platform.
In opposite to Win32, there are no main thread in UWP applications, because in UWP application each top-level window runs on its own thread. Our application has only one top-level window so it has one UI thread and also it has event handling thread and renderer thread (creating new top-level window will require some adaptive changes in our application).
Limitations of WinRT platform
WinRT has a huge amount of new functionality that makes it an exciting development platform and from GUI developer perspective it has a lot of significant benefits over WPF such as the ability to combine XAML and DirectX together and better managed and unmanaged code integration with new C++/CX compiler and COM based WinRT components. But from other side, WinRT has a number of limitations that developers who migrate their code from WPF to WinRT should be aware of. Below I briefly described those limitations.
COM based components limitations
WinRT components actually are not classes they are COM objects, so they can not be inherited and can only be used as a set of interfaces, that is why we use sealed keyword with the component class declaration in C# and C++. In my opinion this is significant disadvantage that breaks the object oriented paradigm.
The lack of synchronous methods in API
WinRT asynchronous API is useful when I have an button click handler that opens a file, for example. In this case async/await keywords help me to write a code that does not block UI thread. But what if I already have a separate non-UI thread that opens a file? Why should I use asynchronous API if my separate thread does not block anything?
The possible solution in this case is to use old C-style API like ::CreateFile2, for example.
How to multiply a value by a constant in WinRT XAML
The easiest way to accomplish this task is to use converter provided below. It is written in C++ but this convertor can be easily converted to C#:
[Windows::Foundation::Metadata::WebHostHidden] public ref class MultiplicationConverter sealed : Windows::UI::Xaml::Data::IValueConverter { public: virtual Platform::Object^ Convert(Platform::Object^ value, Windows::UI::Xaml::Interop::TypeName targetType, Platform::Object^ parameter, Platform::String^ language); virtual Platform::Object^ ConvertBack(Platform::Object^ value, Windows::UI::Xaml::Interop::TypeName targetType, Platform::Object^ parameter, Platform::String^ language); private: Platform::Object^ InternalConvert(Platform::Object^ value, Platform::Object^ parameter, bool forward); };
Dynamic splitter control for Universal Windows App (UWP)
I developed some prototype of a custom layout panel on Universal Windows Platform called DynamicSplitter that contains multiple child panes and arranges them horizontally or vertically depending on its IsHorizontal property of type bool. To support heterogeneous layout of panes, DynamicSplitter itself is used as the child pane of another DynamicSplitter with different IsHorizontal property. So, for example, the parent splitter can have two panes split horizontally one of which is a user control and other is the child splitter, and the child splitter can have three panes split vertically and so on.
Regardless of DynamicSplitter has a lot in common with Grid or StackPanel it is inherited directly from Panel and lays out its child panes by overriding MeasureOverride(…) and ArrangeOverride(…) functions:
How to open a project from Git repository in MS Visual Studio 2013
Below I provided the key steps for opening a project in MS Visual Studio 2013 from a Git repository.
First, go to TOOLS->Options->Source Control and select Microsoft Git Provider:
Implementation of WPF’s ICollectionView interface
The existing ICollectionView implementations in WPF, for example ListCollectionView, work very good in trivial cases, they even can sort and filter the items from the underlying collection, but they have some significant disadvantage: they do not keep the correct sort order of an item and they do not filter the item out if its property is changed until ICollectionView.Refresh() method is called explicitly.
To overcome this inconvenience I developed my own implementation of ICollectionView interface that listens to all its items property change events via WeakEventManager and fires corresponding collection change events to re-soft or re-filter the item if needed. It was not a very simple task for me, and I even debugged WPF source code a bit and realized that it works a bit strange, for example, ItemsControl cannot work with my ICollectionView implementation directly, instead it creates some CollectionViewProxy that wraps it and uses some proxy enumerator to access an item by index:
Debugging .NET Framework with Visual Studio 2013
Visual Studio 2013 allows easily to debug .NET 4.5.1 Framework source code. If you use a previous version of .NET (4.5 or earlier) change the target .NET version of the your projects to 4.5.1 or higher. If you have some C++ CLI projects modify TargetFrameworkVersion attribute manually in all *.vcxproj files:
<PropertyGroup Label="Globals"> ... <TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion> ... </PropertyGroup>
then go to Tools->Options->Debugging->General and check/uncheck the following options:
My experience with WPF
When I worked on some navigation system I developed so called “Control Panel” with various custom WPF controls: