Starting in version 16.1, theming support has been added to the Connexion and Gateway UIs. We’ve added a ‘dark’ mode in addition to the existing ‘light mode’. When starting up, the UI will check the operating system theme and automatically use either light or dark mode. You can manually toggle between light and dark mode by clicking the theme glyph in the top right corner.
Theme support has been added to most of the built-in Connexion controls commonly used by third-party device developers, however, your devices may not be able to take advantage of theming without some minor updates. Below is a guide to supporting themes in your own devices.
We have also switched almost entirely to vector images, which should provider a crisper visual appearance when running >100% scaling. We recommend you include/define your own images as we do update ours from time-to-time, however, you may use images from our vector library by adding a reference to the Connexion.Share.Ui.Images assembly and using the static resource syntax:
Vector image support has been added for the main device icons and is described at the end of this document.
Theming
By default, all native controls support theming. Using style-less controls, your devices will automatically support dark mode. It is important to not set explicit backgrounds or foregrounds unless the colors work in both light and dark mode.
If you have elements within your device UI which require customization based on theme (ie, you wish to specify different colors depending on which theme is selected) then you have the following options:
Add a reference to Connexion.Share.Ui.Style and use one of our existing resources. Attached to this document are the dark.xaml and light.xaml files which define variables used within Connexion. You may dynamically reference one of these.
2. Use code-behind to detect the theme (and when it changes) and use xaml bindings/styles to set the resources. In your viewmodel (or view class) you can use the IThemeProvider interface to hook theme infrastructure.
3. Bind to the IsDarkMode
property directly in your XAML (Available in 16.1 R3 and newer):
<TextBlock> <TextBlock.Style> <Style TargetType="TextBlock"> <Setter Property="Text" Value="LightMode" /> <Style.Triggers> <DataTrigger Binding="{Binding Source={x:Static core:ThemeBinding.GlobalTheme}, Path=IsDarkMode, Mode=OneWay}" Value="true"> <Setter Property="Text" Value="DarkMode" /> </DataTrigger> </Style.Triggers> </Style> </TextBlock.Style> </TextBlock>
Specifically: Binding="{Binding Source={x:Static core:ThemeBinding.GlobalTheme}, Path=IsDarkMode, Mode=OneWay}"
You will need to add a reference to Connexion.Core
in your XAML header (xmlns:core="Connexion.Core....
)
Connexion Look & Feel
Within Connexion we have a general look and feel with our devices. If you wish to replicate this in your own devices, we recommend the following.
Device Background
For most device UIs, you should not set a background brush. The default value is ‘WorkspaceBackgroundLight’ which works well for UIs without a tabbed UI. For tabbed UIs, we set the background to ‘WorkspaceBackground’, which is darker than default (when in dark mode, otherwise it stays white in the Light theme).
Tabbed UI
We use left-aligned tabs styled with the ‘LeftTab’ style:
<TabControl Style="{StaticResource LeftTabControl}"> <TabItem> <TabItem.Header> <TextBlock Text="FTP Connection" Style="{StaticResource LeftTabLabel}" /> </TabItem.Header> <ftp:FtpControl Config="{Binding Config.FtpConfiguration, Mode=OneWay}" DeviceUiParams="{Binding DeviceUIParams}" QueryCertificatesProxy="{Binding DeviceProxy, Mode=OneWay}" Margin="10" ShowTestConnectionButton="True" x:Name="FtpControl" /> </TabItem> ...
Headered Content
When working with 2-toned UIs (for example, a header text area which should contrast with a content text area), we use the ‘HighlightBrush’ resource. This resource also works well with overlays.
Vector Primary Device Icons
As mentioned above, you can use a vector-based primary device icon for better clarity at higher dpis. This is done by returning null from the DeviceImage property (which is used for bitmap-based images) and instead overriding the DeviceImageSource property.
The DrawingImageSourceFromResource method takes the path to a xaml-defined vector image file and the key of the image within that file. If you return a value from DeviceImage, it will take precedence over the DeviceImageSource property.
Custom Resource Dictionaries
In 16.1R3 and higher, you can add your own resource dictionaries to the main application styles dictionary. If you’ve created an assembly containing a shared resource dictionary (ie, the styles are defined in a different assembly), you must use a specific overload in your UI constructor.
Typically your UI constructor uses the XamlInitializer.Initialize(this)
call. Instead, use the overload with the following signature: XamlInitializer.Initialize(this, typeof(your_resource_dictionary), Func<your_resource_dictionary>);
public MyDeviceUi() { XamlInitializer.Initialize(this, typeof(my_resource_dictionary), () => new my_resource_dictionary()); } public MyDeviceUi(MyDeviceConfiguration config, IDeviceUIParams deviceUIParams) : this() { ... }