WPF
Introduction¶
WPF or Windows Presentation Foundation is a Windows UI solution that is part of .NET Windows.
It is developed in 2006 by Microsoft as a successor to another very popular Windows UI framework WinFroms.
WPF allows you to create very rich and sophisticated UI, it separates the code from UI by using XAML which is a XML based language developed by Microsoft.
As of writing this documentation cTrader desktop is also a WPF application and all of it's fancy UI is powered by it.
If you want to develop a cBot or an indicator that need pixel perfect rich UI then you can use WPF.
You should use WPF only if you need a mature heavy UI technology, for other lightweight UI you can use cTrader Automate chart controls or WinFroms.
WPF has a very deep and long learning curve, if you already have experience with WPF then you can skip WinFroms and use it on your cBots/Indicators, otherwise you have to put some good amount of time to learn it.
For more about WPF please check it's documentation.
To use WPF you have to change your cTrader Automate Compiler from Embedded to SDK.
We will use Visual Studio with .NET SDK compiler not the Embedded compiler for the rest of this guide, if you don't have them please install both on your system.
Configuring Project¶
Before you be able to use WPF on your cBot/Indicator you have to make some changes on your indicator/cBot project file.
cTrader indicators and cBots uses .NET cross platform class library like project configuration, as WPF only works on Windows you have change the target of your indicator/cBot to Windows flavor of .NET.
To do that, open your indicator/cBot project file by double clicking on your project file in Visual Studio, then replace it's content with:
1 2 3 4 5 6 7 8 9 10 |
|
We added UseWpf and changed the TargetFramework from net6.0 to net6.0-windows.
After changing your project file you also have to change the access rights of your indicator/cBot to FullAccess, otherwise it will not be able show a window.
Rebuild your project and you can start using WPF now.
If rebuild fails change the cTrader Automate compiler from Embedded to SDK, to do that go to your cTrader settings -> Automate section and select the SDK compiler instead of Embedded.
Creating and Showing a Window¶
It all starts from creating a WPF window and then being able to show it from your cTrader Indicator/cBot.
Here we will use an indicator and for cBots the process is same.
After you configured your indicator project file and added UseWpf tag, add a WPF window to your indicator project by right clicking on your project file and selecting Add -> Window (WPF)... option:
It will open the Add new item dialog box and it will select automatically the WPF Window from the list, set the Window name to "MainWindow" and click "Add" button.
The new WPF window will appear on your indicator project solution explorer, it will have two files, one for XAML and another which will contain the code behind of window.
Open the window XAML file and change it's background color to "SlateGray":
1 2 3 4 5 6 7 8 9 10 |
|
Then Paste the following code on your indicator main source file:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
|
When you add a WPF window it will use your Indicator/cBot namespace, check the namespace of added window and then add it's using to your indicator/cBot source code file, in our case it was "WPF_Test".
Rebuild the indicator either from Visual Studio or cTrader Automate.
After your indicator built finished successfully create an instance of it by attaching it on a chart, and your WPF window should appear:
Sample Trading Panel¶
Let's create a sample trading panel with WPF, create a new cBot and set it's name to WPF Trading Panel.
Open it in Visual Studio, make the necessary changes on project file as described earlier, then add a new WPF window on it, set the window name to "MainWindow":
Open the Window XAML file, and paste the following code on it:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
|
After that open the MainWindow code behind file (.cs) and paste the following code on it:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
|
Now our window is ready, but we have to launch it from our cBot, open your cBot main source file, and then paste the following code on it:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
|
Rebuild the cBot from Visual Studio, if there is any error try to fix it.
Once it got built successfully create an instance of it and start it, you should see this window:
Select a symbol from it's symbols list, and click on Execute button, it should open a new market order for that symbol, play with it.
Our WPF Trading Panel doesn't work very good, but it works.
For sending commands to cBot we used the code behind file of our Window, if you are going to develop something please follow theses guidelines:
- Create a service for managing the interaction with cBot by using it's BeginInvokeOnMainThread method
- If you are building something serious use MVVM, IoC, and decouple your business from UI (Prism maybe a good option)
- For making your UI better you can use MahApps.Metro or any other third party WPF controls
Using a Dedicated Thread for UI¶
When running your WPF UI related code you have to use an STA marked thread because Windows Forms and WPF windows must run inside a STA marked thread otherwise they will not work.
For more detail regarding STA thread apartment check STAThreadAttribute and CA2232.
You can't change a running thread ApartmentState, because the main cBot/Indicator thread is not a STA marked you have to create a new thread and use it only for your UI related stuff.
Accessing API Members From UI Thread¶
As we explained before you have to use a separate dedicated thread to run the window, and only code executing by this thread will be able to access the controls, bindings, and other thins related to your UI.
The same is through for cTrader Automate API members, as API is not thread safe you can't access the API members from the UI thread, you have to dispatch the work by using your indicator/cBot BeginInvokeOnMainThread method.
It will add a bit of complexity when you want to exchange data between your indicator/cBot and the UI thread.
You can create a proxy class that will manage the interactions between your cBot/Indicator and UI threads.