Download XamlFontApp_X11_32.zip
Download XamlFontApp_X11_64.zip
Download XamlFontApp_Win7.zip
Introduction
This article is a case study, how to write a MVVM (Model View ViewModel) design pattern based X11 application (utilizing massive data binding with zero code) with XAML using the Roma Widget Set (Xrw). The Roma Widget Set is a zero dependency GUI application framework for X11 (it requires only assemblies of the free Mono standard installation and libraries of the free X11 distribution; it doesn't particularly require GNOME, KDE or commercial libraries) and is implemented entirely in C#.
This article continues the works Writing a XAML dialog application for X11 and Writing a XAML ribbon application for X11. As far as i know, this (utilizing the Xrw) is the first attempt to use XAML for X11 application development after the abandonment of Moonlight.
Neither the Roma Widget Set nor the XAML implementation are complete. This sample application is intended as a more complex 'proof of concept' and checks out if and how it is possible bo create MVVM design pattern based X11 application with XAML.
Since this third attempt to use XAML for a X11 application development has been successful, other articles about XAML using the Roma Widget Set on X11 will follow centenly.
Background
The Motivation and the general Concept to use XAML for X11 application development are already explained in the Writing a XAML dialog application for X11 article.
Focus
While the first article Writing a XAML dialog application for X11 demonstrated, that with XAML
- a window containing some controls can be defined and
- click events can be connected to buttons,
and the second article Writing a XAML ribbon application for X11 demonstrated, that with XAML
- a window containing a ribbon command interface can be defined,
- static window resources (this sample has a resource converter and a ModelView) can be defined,
- a ModelView can be assigned to a control's data context as a static resource,
- a resource converter can be applied to a control's property as a static resource,
- commands can be bound to buttons via the "RelayCommand" approach,
- control properties can be bound to the data context and
- controls can be updated via the
INotifyPropertyChanged
interface,
this article shall demonstrate that with XAML
- massive data binding can provide a useful functionality and
- an application with zero code behind can be defined.
Using the code
The sample application was written with Mono Develop 2.4.1 for Mono 2.8.1 on OPEN SUSE 11.3 Linux 32 bit EN and GNOME desktop. Neither the port to any older nor to any newer version should be a problem. The sample application's solution consists of two projects (the complete sources are provided for download):
- XamlFontApp contains the source code of the sample application.
- XamlPreprocessor contains the source code of the XAML preprocessor.
The sample application is also tested with Mono Develop 3.0.6 for Mono 3.0.4 on OPEN SUSE 12.3 Linux 64 bit DE and GNOME desktop, IceWM, TWM und Xfce.
The only difference between the 32 bit and the 64 bit solution is the definition of some X11 specific data types, as already described in the Programming Xlib with Mono develop -Part 1: Low level (proof of concept) article.
The Xlib/X11 window handling is based on the X11Wrapper assembly version 0.7, that defines the function prototypes, structures and types for Xlib/X11 calls to the libX11.so. This assembly has been developed for the Programming Xlib with Mono Develop - Part 1: Low-level (proof of concept) project and has been advanced during the Programming the Roma Widget Set (C# X11) - a zero dependency GUI application framework - Basics project.
The GUI framework is based on the Xrw assembly version 0.7, that defines the widgets/gadgets and its wrapper classes used within the XAML code (that should be as near to the Microsoft® original as reasonable). This assembly has been developed during the Programming the Roma Widget Set (C# X11) - a zero dependency GUI application framework - Basics project.
Advice: To use the class library documentation shortcut (F1) from MonoDevelop, the "mono-tools" package has to be installed.
The first image shows the sample application on OPEN SUSE 11.3 Linux 32 bit EN and GNOME desktop.
The second image shows the sample application on OPEN SUSE 12.3 Linux 64 bit DE and Xfce.
The third image shows the sample application on Windows® 7 64 Bit Edition.
The sample application provides a Font Family selection list, a Family Typefaces selection list and a Font Size slider. Any font change will be shown by the preview text immediately.
The sample application is based on the ideas behind the article Pure XAML Font Choose by Norris Cheng. The specific challenge was to realize the full functionality with zero code behind for X11.
Walk through
The Project setup, Application file context (except the theme) and Preporocessor code generation steps are exactly the same as in Writing a XAML dialog application for X11. Please refer to this article, if a new solution shall be created from scratch.
Main view file context
The XAML (MainView.xaml)
First the XAML file of the window.
<Window x:Class="XamlFontApp.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:src="clr-namespace:XamlFontApp"
DataContext="src:MainViewModel"
Name="MainWindow" Title="XAML font application"
Width="750" Height="400" Icon="XrwIcon16.bmp">
<Window.Resources>
</Window.Resources>
<Grid Name="MainGrid" Background="#FFEBEBEB">
<Grid.Resources>
</Grid.Resources>
<Grid.Datacontext>
</Grid.Datacontext>
<Grid.RowDefinitions>
<RowDefinition Height="10"/>
<RowDefinition Height="28"/>
<RowDefinition Height="*"/>
<RowDefinition Height="28"/>
<RowDefinition Height="10"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="10"/>
</Grid.ColumnDefinitions>
<Label Name="FontFamiliesLabel" Grid.Column="1" Grid.Row="1" FontSize="14"
FontWeight="Bold" Content="Font Family" Background="#FFEBEBEB" />
<ListView Name="FontFamiliesListView" Grid.Column="1" Grid.Row="2"
ItemsSource="{x:Static Fonts.SystemFontFamilies}" >
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn Header="Source"
DisplayMemberBinding="{Binding Source}" />
<GridViewColumn Header="Baseline"
DisplayMemberBinding="{Binding Baseline}" />
<GridViewColumn Header="LineSpacing"
DisplayMemberBinding="{Binding LineSpacing}" />
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
<Label Name="SelectedFontFamilyLabel" Grid.Column="1" Grid.Row="3"
Content="{Binding SelectedItem.Source, ElementName=FontFamiliesListView, Mode=OneWay}"
Background="#FFEBEBEB" />
<Label Name="FamilyTypefacesLabel" Grid.Column="3" Grid.Row="1"
FontSize="14" FontWeight="Bold" Content="Family Typefaces" Background="#FFEBEBEB" />
<ListView Name="FamilyTypefacesListView" Grid.Column="3" Grid.Row="2"
ItemsSource="{Binding SelectedItem.FamilyTypefaces,
ElementName=FontFamiliesListView, Mode=OneWay}" >
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn Header="Style" DisplayMemberBinding="{Binding Style}" />
<GridViewColumn Header="Weight" DisplayMemberBinding="{Binding Weight}" />
<GridViewColumn Header="Stretch" DisplayMemberBinding="{Binding Stretch}" />
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
<Label Name="SelectedFamilyTypefacesLabel" Grid.Column="3" Grid.Row="3"
Content="{Binding SelectedItem.Style, ElementName=FamilyTypefacesListView, Mode=OneWay}"
Background="#FFEBEBEB" />
<Slider Name="FontSizeSlider" Grid.Column="5" Grid.Row="1" Orientation="Horizontal"
Minimum="6" Value="12" Maximum="72" SmallChange="1" LargeChange="8" />
<TextBlock Name="TextSimulation" Grid.Column="5" Grid.Row="2"
Text="The quick brown fox jumps over the lazy dog."
FontFamily="{Binding SelectedItem.Source, ElementName=FontFamiliesListView}"
FontWeight="{Binding SelectedItem.Weight, ElementName=FamilyTypefacesListView}"
FontStretch="{Binding SelectedItem.Stretch, ElementName=FamilyTypefacesListView}"
FontStyle="{Binding SelectedItem.Style, ElementName=FamilyTypefacesListView}"
FontSize="{Binding Value, ElementName=FontSizeSlider}" TextWrapping="Wrap"
Background="#FFF8F8F8" />
<Label Name="FontSizeLabel" Grid.Column="5" Grid.Row="3" Background="#FFEBEBEB"
Content="{Binding Value, ElementName=FontSizeSlider, Mode=OneWay}" />
</Grid>
</Window>
The complete XAML code is fully Microsoft® compatible.
Compared to Writing a XAML ribbon application for X11, only the enhancments and differences will be discussed.
The Label
will be defined (in addition to the already known features) by:
- The
Background
attribute defines the background color. This attribute is is optional. The syntax of the attribute is a hexadecimal value #AARRGGBB
with AA
for alpha, RR
for red, GG
for green and BB
for blue. Currently the alpha value is not implemented. - The
FontSize
attribute defines the font size. This attribute is is optional. The syntax of the attribute is a decimal value. Bitmap fonts (in contrast to vector fonts) do not support any font size. Their font size will fall back to the nearest supported font size, if any unsupported font size is specified. - The
FontWeight
attribute defines the font weight. This attribute is is optional. The syntax of the attribute is the string representation of any System.Windows.FontWeight
value. Typical values are Light
, Regular
and Bold
. The fallback value is Regular
. Mind that Windows® fonts typically use the font weight value Normal
while X11 fonts typically use the font weight value Regular
for equivalent font weight. Most of the default font falilies support only a few font wights and some font weights are not supported by any of the default font falilies.
The ListView
will be defined (in addition to the already known features) by:
- The
ItemSource
attribute defines the data source to create the items to display from. This attribute is is optional. The syntax of the attribute can be either {x:Static
<resource name>}
for static resources or {Binding
<path>, ElementName=
<control name>, Mode=
<mode>}
for dynamic resources. The data source must implement System.Collections.IEnumerable
. A dynamic data source should implement INotifyPropertyChanged
as well. Currently the Mode
is not implemented.
The Slider
will be defined by:
- The
Name
attribute defines the class instance name, that can be used to identify the class instance uniquely. This attribute is is recommended, or mandatory if this class instance has to be accessible through C# code. - The
Grid.Column
attribute defines the zero-based column index, the control has to be positioned inside a grid. The default value is 0. This attribute is recommended for a grid child, but mandatory for controls positioned not on column 0 inside a grid. The index must not exceed the available grid rows. - The
Grid.Row
attribute defines the zero-based row index, the control has to be positioned inside a grid. The default value is 0. This attribute is recommended for a grid child, but mandatory for controls positioned not on row 0 inside a grid. The index must not exceed the available grid rows. - The
Orientation
attribute defines the orientation. This attribute is optional. The default value is Horizontal. - The
Minimum
attribute defines the smallest possible value. This attribute is is optional. The default value is 0.0F. - The
Maximum
attribute defines the greatest possible value. This attribute is is optional. The default value is 100.0F. - The
Value
attribute defines the currently selected value. This attribute is is optional. The default value is Minimum
. - The
SmallChange
attribute is currently not implemented. - The
LargeChange
attribute is currently not implemented.
The TextBlock
(is similar to Label
but supports automatic line break) will be defined by:
- The
Name
attribute defines the class instance name, that can be used to identify the class instance uniquely. This attribute is is recommended, or mandatory if this class instance has to be accessible through C# code. - The
Grid.Column
attribute defines the zero-based column index, the control has to be positioned inside a grid. The default value is 0. This attribute is recommended for a grid child, but mandatory for controls positioned not on column 0 inside a grid. The index must not exceed the available grid rows. - The
Grid.Row
attribute defines the zero-based row index, the control has to be positioned inside a grid. The default value is 0. This attribute is recommended for a grid child, but mandatory for controls positioned not on row 0 inside a grid. The index must not exceed the available grid rows. - The
Text
attribute defines the text to display. This attribute is optional. The default value is an empty string. - The
FontFamily
attribute defines the font family name. This attribute is is optional. The syntax of the attribute is either <font family name> like Arial or <font foundry name>-
<font family name> like Adobe-Utopia. The first syntax is fully Microsoft® compatible, the second syntax is necessary due to the X11 font specification. - The
FontWeight
attribute defines the font weight. This attribute is is optional. The syntax of the attribute is the string representation of any System.Windows.FontWeight
value. Typical values are Light
, Regular
and Bold
. The fallback value is Regular
. Mind that Windows® fonts typically use the font weight value Normal
while X11 fonts typically use the font weight value Regular
for equivalent font weight. Most of the default font falilies support only a few font wights and some font weights are not supported by any of the default font falilies. - The
FontStretch
attribute defines the font stretch. This attribute is is optional. The syntax of the attribute is the string representation of any System.Windows.FontStretch
value. Typical values are SemiCondensed
, Medium
and SemiExpanded
. The fallback value is Medium
. Most of the default font falilies support only a few font stretches and some font stretches are not supported by any of the default font falilies. - The
FontStyle
attribute defines the font style. This attribute is is optional. The syntax of the attribute is the string representation of any System.Windows.FontStyle
value. Typical values are Normal
, Italic
and Oblique
. The fallback value is Normal
. Not all of the default font falilies support every font style. - The
FontSize
attribute defines the font size. This attribute is is optional. The syntax of the attribute is a decimal value. Bitmap fonts (in contrast to vector fonts) do not support any font size. Their font size will fall back to the nearest supported font size, if any unsupported font size is specified.
The code behind (MainView.xaml.cs)
The corresponding C# code file of the main view is MainView.xaml.cs
. It is in initial state and thus almost empty.
using System;
using X11;
using Xrw;
using XrwXAML;
namespace XamlFontApp
{
public partial class MainView : XrwXAML.Window, IView
{
public MainView ()
: base (-1, -1)
{
InitializeComponent ();
}
}
}
Main view model file context
The MainWindowViewModel.cs
file remains in initial state. There is no functionality provided to the application by the ViewModel.
Main model file context
The MainModel.cs
file remains in initial state. There is no functionality provided to the application by the Model.
Points of Interest
It is amazing to create as much functionality without any line if code! (And fully compatible with Microsoft®.)
The first three articles about "Writing a XAML application for X11" have shown, hat single view applications can be written with fully portable code for Windows® and X11. The next step should prove this for applications with multiple views.
Since 02. February 2015 the article Writing a XAML calculator application for X11 continues the XAML topic.
History
The first version of this article is from 22. November 2014.
The first reviewed version is from 19. February 2015.
The second reviewed version is from 19. February 2015.