Monday, April 24, 2017

WPF ValueConverters


As a name suggest "Converter",  convert the values. wpf converters use in data binding and work as a bridge for bind-able properties (source) and ui display(target) , it can be use when source and target property object are different, then "Converter" manipulate the data from source to target and also convert back from target to source.

wpf provideIValueConverter interface, to create a value converter class we need to implement IValueConverter interface.

IValueConverter interface provide two methods, Convert() and ConvertBack().

Convert method gets called when source updates target object.
ConvertBack method gets called when target updates source object.

Problem : Suppose we have a case where we need to bind the integer (0, 1) value to the checkbox,  where we assume 0 is for false and 1 is for true.

Code : 

So let's building an application.

add a wpf project and and add textbox and checkbox in MainWindow.xaml as follows:

<Window x:Class="WPF.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="IValueConverter" Height="91" Width="284"
        xmlns:local="clr-namespace:WPF">
    <Window.Resources>
        <local:BooleanIntegerConverter x:Key="YesNoToBooleanConverter"/>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="27*"/>
            <RowDefinition Height="34*"/>
        </Grid.RowDefinitions>
        <TextBox Name="txtBoolValue" HorizontalAlignment="Center" Margin="0" TextWrapping="Wrap" Text="0" HorizontalContentAlignment="Center" VerticalAlignment="Center" Height="20" Width="178" />
        <CheckBox Content="CheckBox" HorizontalAlignment="Center"  VerticalAlignment="Center" Grid.Row="1" Margin="0" Height="13" Width="62"
                  IsChecked="{Binding ElementName=txtBoolValue, Path=Text, Converter={StaticResource YesNoToBooleanConverter}}"/>

    </Grid>
</Window>

now create converter 

We will add a new class called BooleanIntegerConverter that implements IValueConverter interface.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;

namespace WPF
{
    public class BooleanIntegerConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter,
               System.Globalization.CultureInfo culture)
        {
            switch (value.ToString().ToLower())
            {
                case "0":
                    return false;
                case "1":
                    return true;

                default:
                    return Binding.DoNothing;
            }
        }

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


Convert() method will receive string value "0" or "1" and return false or true respectively,
and convert back will receive bool true or false and return 1 or 0 respectively.

Saturday, April 22, 2017

How to create a Dependency Property in a UserControl and how use it

You can refer the topic Read my post : How to create a dependency property in my blog.

Problem : we need to create a user control which having label and textbox in combine and we can change the label ,text and fore color of textbox where it is use.





Add a UserControl 

Put Label and textbox in XAML

<UserControl x:Class="CustomDP1.LabelTextBox"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             mc:Ignorable="d" d:DesignWidth="300" Height="36.091">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="40*"/>
            <ColumnDefinition Width="60*"/>
        </Grid.ColumnDefinitions>
        <Label Content="Label" Name="lblDispaly" HorizontalAlignment="Stretch" Margin="0" VerticalAlignment="Stretch" Background="Gray"/>
        <TextBox Grid.Column="1" Name="txtDispaly" HorizontalAlignment="Stretch" Margin="0" VerticalAlignment="Stretch" TextWrapping="Wrap"  />
    </Grid>
</UserControl>




Create three Dependency property 
  • TextBoxForeColorProperty 
  • LabelTextProperty 
  • TextBoxTextProperty 

    /// <summary>
    /// Interaction logic for LabelTextBox.xaml
    /// </summary>
    public partial class LabelTextBox : UserControl
    {
        public LabelTextBox()
        {
            InitializeComponent();
            this.Loaded += LabelTextBox_Loaded;
        }

        void LabelTextBox_Loaded(object sender, RoutedEventArgs e)
        {
            lblDispaly.Content = LabelText;
            txtDispaly.Text = TextBoxText;
            txtDispaly.Foreground = TextBoxForeColor;
        }

        public static readonly DependencyProperty TextBoxForeColorProperty = DependencyProperty.Register(
        "TextBoxForeColor",
        typeof(Brush),
        typeof(LabelTextBox),
        new PropertyMetadata(new SolidColorBrush(Colors.WhiteSmoke)));

        public Brush TextBoxForeColor
        {
            get { return (Brush)GetValue(TextBoxForeColorProperty); }
            set { SetValue(TextBoxForeColorProperty, value); }
        }


        public static readonly DependencyProperty LabelTextProperty = DependencyProperty.Register(
       "LabelText",
       typeof(string),
       typeof(LabelTextBox),
       new PropertyMetadata(null));

        public string LabelText
        {
            get { return (string)GetValue(LabelTextProperty); }
            set { SetValue(LabelTextProperty, value); }
        }


        public static readonly DependencyProperty TextBoxTextProperty = DependencyProperty.Register(
        "TextBoxText",
        typeof(string),
        typeof(LabelTextBox),
        new PropertyMetadata(null));

        public string TextBoxText
        {
            get { return (string)GetValue(TextBoxTextProperty); }
            set { SetValue(TextBoxTextProperty, value); }
        }
    }

Use this User control

Add the namespace of usercontrol
Add user control
now we can add values in custom dp(s)

<Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:CustomDP1" x:Class="CustomDP1.MainWindow"
        Title="Custom Control" Height="165.789" Width="501.316">
    <Grid>
        <local:LabelTextBox HorizontalAlignment="Left" VerticalAlignment="Top" Height="36" Width="356" LabelText="my label" TextBoxForeColor="Red"
                            TextBoxText="my custom textbox" Margin="59,45,0,0"/>
    </Grid>
</Window>

We can put these dp(s) values or bind with view model properties.