Use await in Class Constructor in C#

use a static async method that returns a class instance created by a private constructor

public class ViewModel       
{       
    public ObservableCollection<TData> Data { get; set; }       

    //static async method that behave like a constructor       
    async public static Task<ViewModel> BuildViewModelAsync()  
    {       
        ObservableCollection<TData> tmpData = await GetDataTask();  
        return new ViewModel(tmpData);
    }       

    // private constructor called by the async method
    private ViewModel(ObservableCollection<TData> Data)
    {
        this.Data = Data;   
    }
}

References
https://stackoverflow.com/questions/8145479/can-constructors-be-async

Implementing the Singleton Pattern in C#

    public sealed class EventBus
    {
        private static readonly EventBus instance = new EventBus();

        // Explicit static constructor to tell C# compiler
        // not to mark type as beforefieldinit
        static EventBus()
        {
        }

        private EventBus()
        {
        }

        public static EventBus Instance
        {
            get { return instance; }
        }
    }

Using .NET 4’s Lazy<T> type

public sealed class Singleton5    
{    
    private Singleton5()    
    {    
    }    
    private static readonly Lazy<Singleton5> lazy = new Lazy<Singleton5>(() => new Singleton5());    
    public static Singleton5 Instance    
    {    
        get    
        {    
            return lazy.Value;    
        }    
    }    
}

 

References
https://csharpindepth.com/articles/singleton
https://www.c-sharpcorner.com/UploadFile/8911c4/singleton-design-pattern-in-C-Sharp/
https://riptutorial.com/csharp/example/6795/lazy–thread-safe-singleton–using-lazy-t–

Value conversion with IValueConverter in WPF

<Window x:Class="WpfTutorialSamples.DataBinding.ConverterSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfTutorialSamples.DataBinding"
        Title="ConverterSample" Height="140" Width="250">
    <Window.Resources>
        <local:YesNoToBooleanConverter x:Key="YesNoToBooleanConverter" />
    </Window.Resources>
    <StackPanel Margin="10">
        <TextBox Name="txtValue" />
        <WrapPanel Margin="0,10">
            <TextBlock Text="Current value is: " />
            <TextBlock Text="{Binding ElementName=txtValue, Path=Text, Converter={StaticResource YesNoToBooleanConverter}}"></TextBlock>
        </WrapPanel>
        <CheckBox IsChecked="{Binding ElementName=txtValue, Path=Text, Converter={StaticResource YesNoToBooleanConverter}}" Content="Yes" />
    </StackPanel>
</Window>
using System;
using System.Windows;
using System.Windows.Data;

namespace WpfTutorialSamples.DataBinding
{
    public partial class ConverterSample : Window
    {
        public ConverterSample()
        {
            InitializeComponent();
        }
    }

    public class YesNoToBooleanConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            switch(value.ToString().ToLower())
            {
                case "yes":
                case "oui":
                    return true;
                case "no":
                case "non":
                    return false;
            }
            return false;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if(value is bool)
            {
                if((bool)value == true)
                    return "yes";
                else
                    return "no";
            }
            return "no";
        }
    }
}

References
https://wpf-tutorial.com/data-binding/value-conversion-with-ivalueconverter/

Debug data bindings in WPF using Converter

<Window x:Class="WpfTutorialSamples.DataBinding.DataBindingDebuggingSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:self="clr-namespace:WpfTutorialSamples.DataBinding"
        Title="DataBindingDebuggingSample" Name="wnd" Height="100" Width="200">
    <Window.Resources>
        <self:DebugDummyConverter x:Key="DebugDummyConverter" />
    </Window.Resources>
    <Grid Margin="10">
        <TextBlock Text="{Binding Title, ElementName=wnd, Converter={StaticResource DebugDummyConverter}}" />
    </Grid>
</Window>
using System;
using System.Windows;
using System.Windows.Data;
using System.Diagnostics;

namespace WpfTutorialSamples.DataBinding
{
    public partial class DataBindingDebuggingSample : Window
    {
        public DataBindingDebuggingSample()
        {
            InitializeComponent();
        }
    }

    public class DebugDummyConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            Debugger.Break();
            return value;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            Debugger.Break();
            return value;
        }
    }
}

References
https://wpf-tutorial.com/data-binding/debugging/

Handle and raising events in C#

Events

class Counter
{
    public event EventHandler ThresholdReached;

    protected virtual void OnThresholdReached(EventArgs e)
    {
        EventHandler handler = ThresholdReached;
        handler?.Invoke(this, e);
    }

    // provide remaining implementation for the class
}

Event data

public class ThresholdReachedEventArgs : EventArgs
{
    public int Threshold { get; set; }
    public DateTime TimeReached { get; set; }
}

Event handlers

class Program
{
    static void Main()
    {
        var c = new Counter();
        c.ThresholdReached += c_ThresholdReached;

        // provide remaining implementation for the class
    }

    static void c_ThresholdReached(object sender, EventArgs e)
    {
        Console.WriteLine("The threshold was reached.");
    }
}

References
https://docs.microsoft.com/en-us/dotnet/standard/events/
https://www.tutorialsteacher.com/csharp/csharp-event

Bind DataContext to ViewModel in WPF

<Window x:Class="desktop.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
        xmlns:svgc="http://sharpvectors.codeplex.com/svgc/"
        xmlns:local="clr-namespace:desktop.viewmodel"
        Title="Monitoring" Height="350" Width="525" Loaded="MainWindow_OnLoaded" WindowState="Maximized">
    <Window.DataContext>
        <local:MainWindowViewModel x:Key="ViewModel" />
    </Window.DataContext>
    <DockPanel>
        <telerik:RadMenu Name="MenuMain" VerticalAlignment="Top" DockPanel.Dock="Top">
            <telerik:RadMenuItem Header="Item 1">
                <telerik:RadMenuItem Header="SubItem 1" />
                <telerik:RadMenuItem Header="SubItem 2" />
            </telerik:RadMenuItem>
            <telerik:RadMenuItem Header="Item 2" />
        </telerik:RadMenu>
        <telerik:RadBusyIndicator IsBusy="{Binding  Path=IsBusyIndicatorBusy}">
            <Frame Name="FrameMain" NavigationUIVisibility="Hidden" />
        </telerik:RadBusyIndicator>

    </DockPanel>
</Window>
public partial class MainWindow : Window
    {
        public MainWindowViewModel ViewModel { get; set; }

        public MainWindow()
        {
            InitializeComponent();
            Init();
        }

        private void Init()
        {
            ViewModel = (MainWindowViewModel) DataContext;
        }
     }

ViewModelBase

public abstract class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected bool SetProperty<T>(ref T field, T newValue, [CallerMemberName]string propertyName = null)
    {
        if(!EqualityComparer<T>.Default.Equals(field, newValue))
        {
            field = newValue;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
            return true;
        }
        return false;
    }
}

ViewModel

using System.ComponentModel;
using System.Runtime.CompilerServices;
using desktop.Annotations;
using Telerik.Windows.Controls;

namespace desktop.viewmodel
{
    public class MainWindowViewModel : ViewModelBase
    {

        private bool _isBusyIndicatorBusy = false;

        public bool IsBusyIndicatorBusy
        {
            get => _isBusyIndicatorBusy;
            set
            {
                _isBusyIndicatorBusy = value;
                SetProperty(ref _isBusyIndicatorBusy , value);
            }
        }
    }
}

References
https://stackoverflow.com/questions/25267070/setting-datacontext-of-elements-inside-xaml
https://intellitect.com/blog/getting-started-model-view-viewmodel-mvvm-pattern-using-windows-presentation-framework-wpf/