Here’s an example of single window application using the Avalonia UI Framework
The application use a single window to display pages and has animated transition between pages.
You can find the source code of the project here
Here’s an example of single window application using the Avalonia UI Framework
The application use a single window to display pages and has animated transition between pages.
You can find the source code of the project here
Example about generating random number using the alias method in C#
public static class RandomExtensions
{
public static int GetAlias(this Random rnd, IEnumerable<int> probs)
{
int random = rnd.Next(probs.Sum());
int sum = 0;
int idx = 0;
foreach (var p in probs)
{
sum += p;
if (sum >= random)
break;
idx++;
}
return idx;
} // GetAlias
}
We pass the method a list of int containing the probability we want for that index.
Test program
class Program
{
class Animal
{
public Animal(string name) {
Name = name;
}
public string Name { get; set; }
public int Count { get; set; }
}
static void Main(string[] args)
{
List<Animal> values = new List<Animal>
{
new Animal("Cat"),
new Animal("Dog"),
new Animal("Sheep"),
new Animal("Cow"),
new Animal("Turtle"),
};
int[] probs = new int[] { 10, 50, 10, 10, 20 };
Random rnd = new Random();
for (int i=0; i < 100; i++) {
int number = rnd.GetAlias(probs);
values[number].Count++;
}
foreach (var a in values) {
Console.WriteLine($"{string.Format("{0,-10}", a.Name)}: {string.Format("{0,2}", a.Count)}");
}
}
}
Test program output
Cat : 6
Dog : 49
Sheep : 12
Cow : 11
Turtle : 22
So you want to localize your application developed using the Avalonia UI Framework? Let’s see how it can be done.
Some informations are taken from this bug report.
To localize an application we must be able to
To translate strings in the XAML we can use a custom MarkupExtension and bindings
public class LocalizeExtension : MarkupExtension
{
public LocalizeExtension(string key)
{
this.Key = key;
}
public string Key { get; set; }
public string Context { get; set; }
public override object ProvideValue(IServiceProvider serviceProvider)
{
var keyToUse = Key;
if (!string.IsNullOrWhiteSpace(Context))
keyToUse = $"{Context}/{Key}";
var binding = new ReflectionBindingExtension($"[{keyToUse}]")
{
Mode = BindingMode.OneWay,
Source = Localizer.Instance,
};
return binding.ProvideValue(serviceProvider);
}
}
Note that in addition to the string key there’s also a context, used to have different translations for the same string in different contexts.
This extension can be used in XAML:
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:i18n="clr-namespace:AvaloniaLocalizationExample.Localizer"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="AvaloniaLocalizationExample.MainWindow"
WindowStartupLocation="CenterScreen"
Width="500" Height="350"
Title="AvaloniaLocalizationExample">
<StackPanel Orientation="Vertical" Margin="15">
<Label Content="{i18n:Localize Language}" />
<ComboBox SelectedIndex="0" SelectionChanged="OnLanguageChanged">
<ComboBoxItem>English</ComboBoxItem>
<ComboBoxItem>Italian</ComboBoxItem>
</ComboBox>
<TextBlock FontSize="21" Text="{i18n:Localize HelloWorld}"/>
<TextBlock FontSize="21" Text="{i18n:Localize HelloWorld, Context=Second}"/>
<TextBlock FontSize="21" Text="{i18n:Localize MissingTranslation}"/>
</StackPanel>
</Window>
We need to define the namespace first
xmlns:i18n="clr-namespace:AvaloniaLocalizationExample.Localizer"
then we can bind strings using our MarkupExtension
<TextBlock FontSize="21" Text="{i18n:Localize HelloWorld}"/>
Now we need a way to translate the strings to the desired language. An easy way is to use JSON files containing the context/key with the corresponding translated text. We can embed the JSON files using assets
Missing strings are displayed as the language code followed by a semicolon and the string key.
public class Localizer : INotifyPropertyChanged
{
private const string IndexerName = "Item";
private const string IndexerArrayName = "Item[]";
private Dictionary<string, string> m_Strings = null;
public Localizer()
{
}
public bool LoadLanguage(string language)
{
Language = language;
var assets = AvaloniaLocator.Current.GetService<IAssetLoader>();
Uri uri = new Uri($"avares://AvaloniaLocalizationExample/Assets/i18n/{language}.json");
if (assets.Exists(uri)) {
using (StreamReader sr = new StreamReader(assets.Open(uri), Encoding.UTF8)) {
m_Strings = JsonConvert.DeserializeObject<Dictionary<string, string>>(sr.ReadToEnd());
}
Invalidate();
return true;
}
return false;
} // LoadLanguage
public string Language { get; private set; }
public string this[string key]
{
get
{
string res;
if (m_Strings != null && m_Strings.TryGetValue(key, out res))
return res.Replace("\\n", "\n");
return $"{Language}:{key}";
}
}
public static Localizer Instance { get; set; } = new Localizer();
public event PropertyChangedEventHandler PropertyChanged;
public void Invalidate()
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(IndexerName));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(IndexerArrayName));
}
}
Since we are using bindings and INotifyPropertyChanged the translated text is applied as soon as we load a new language.
To access to the translated strings in the code use the static Localizer using the string key
Localizer.Localizer.Instance["Key"]
You can download the source code here
Intel’s turbo boost can be enabled and disabled in Windows using the command line.
First we need to check the active profile.
powercfg.exe /GETACTIVESCHEME Power Scheme GUID: 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c (High performance)
By default Windows does not display the turbo boost setting via the powercfg utility. To enable it use the command:
powercfg.exe -attributes SUB_PROCESSOR be337238-0d82-4146-a960-4f3749d470c7 -ATTRIB_HIDE
Using the current profile’s GUID 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c we can check if turbo boost is enabled or not.
powercfg.exe /QUERY 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c 54533251-82be-4824-96c1-47b60b740d00 be337238-0d82-4146-a960-4f3749d470c7 Power Scheme GUID: 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c (High performance) GUID Alias: SCHEME_MIN Subgroup GUID: 54533251-82be-4824-96c1-47b60b740d00 (Processor power management) GUID Alias: SUB_PROCESSOR Power Setting GUID: be337238-0d82-4146-a960-4f3749d470c7 (Processor performance boost mode) GUID Alias: PERFBOOSTMODE Possible Setting Index: 000 Possible Setting Friendly Name: Disabled Possible Setting Index: 001 Possible Setting Friendly Name: Enabled Possible Setting Index: 002 Possible Setting Friendly Name: Aggressive Possible Setting Index: 003 Possible Setting Friendly Name: Efficient Enabled Possible Setting Index: 004 Possible Setting Friendly Name: Efficient Aggressive Possible Setting Index: 005 Possible Setting Friendly Name: Aggressive At Guaranteed Possible Setting Index: 006 Possible Setting Friendly Name: Efficient Aggressive At Guaranteed Current AC Power Setting Index: 0x00000000 Current DC Power Setting Index: 0x00000000
The output of the command shows that turbo boost is disabled using AC and using DC:
Current AC Power Setting Index: 0x00000000 Current DC Power Setting Index: 0x00000000
To enable turbo boost in AC:
powercfg.exe /SETACVALUEINDEX 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c 54533251-82be-4824-96c1-47b60b740d00 be337238-0d82-4146-a960-4f3749d470c7 003
To enable turbo boost in DC:
powercfg.exe /SETDCVALUEINDEX 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c 54533251-82be-4824-96c1-47b60b740d00 be337238-0d82-4146-a960-4f3749d470c7 003
The last argument is the index of the turbo boost mode to enable (003 is “Efficient enabled”).
To apply the changes use the command
powercfg.exe -S SCHEME_CURRENT
Reading a Excel file is easy using the SpreadsheetDocument and SheetData classes but this method uses a lot of memory if the Excel file is big.
This is due to the fact that to get the sheet data the framework loads the entire file into memory.
To read huge files it is better to use the OpenXmlReader.
Here’s an example usage of the OpenXmlReader (it also consider the SharedString)
public static IEnumerable> ReadData(string fileName) { using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Open(fileName, false)) { WorkbookPart workbookPart = spreadsheetDocument.WorkbookPart; WorksheetPart worksheetPart = workbookPart.WorksheetParts.FirstOrDefault(); if (workbookPart != null) { using (OpenXmlReader oxr = OpenXmlReader.Create(worksheetPart)) { IEnumerable
sharedStrings = workbookPart.SharedStringTablePart.SharedStringTable.Elements (); while (oxr.Read()) { if (oxr.ElementType == typeof(Row)) { oxr.ReadFirstChild(); List rowData = new List (); do { if (oxr.ElementType == typeof(Cell)) { Cell c = (Cell)oxr.LoadCurrentElement(); string cellValue; if (c.DataType != null && c.DataType == CellValues.SharedString) { SharedStringItem ssi = sharedStrings.ElementAt(int.Parse(c.CellValue.InnerText)); cellValue = ssi.Text.Text; } else { cellValue = c.CellValue.InnerText; } rowData.Add(cellValue); } } while (oxr.ReadNextSibling()); yield return rowData; } } } } } } // GetData
To loop the Excel’s rows
foreach (ListrowData in ReadData(fileName)) { ... }
The OpenXmlReader uses less memory, but it is slow.
For faster reading you can use the ExcelDataReader, it is available also as a NuGet package.