DevCrux Blog - Create. Learn. Make Money
DevCrux Blog - Create. Learn. Make Money
  • General
  • Programming
  • Website Design
  • Apps
  • 3D Modelling
  • Revenue
  • Tutorials
Developer, Programming, Tutorials, UWP, Windows 10

Custom MessageBox in Universal Windows Platform (UWP)

 

For Universal Apps, the new APIs require you to use await MessageDialog().ShowAsync() (in Windows.UI.Popups) to bring it into line with Win 8.1.

var dialog = new MessageDialog("Your message here");
await dialog.ShowAsync();

The above code produces the result shown below:

messagebox

You can go ahead to add your custom commands such as:

dialog.Title = "Delete?";
dialog.Commands.Add(new UICommand { Label = "Yes", Id = 0 });
dialog.Commands.Add(new UICommand { Label = "No", Id = 1 });

The above implementation of message box cannot be customized to fit into your theme without really getting your hands dirty and if you don’t mind you can go ahead.

A cheap way to quickly display a custom message box in your app is to use the ContentDialog in the Universal Windows template.

ContentDialog class represents a dialog box that can be customized to contain checkboxes, hyperlinks, buttons and any other XAML content. Read more here.

To add ContentDialog, Right-Click on your root project folder, Add -> New Item -> ContentDialog, give it a name and add to your project.

contentdialog_add

Then you have this:

contentdialog_default

Your XAML code will look like this:

<ContentDialog
x:Class="CustomMessageBox.MessageDisplay"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:CustomMessageBox"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="TITLE"
PrimaryButtonText="Button1"
SecondaryButtonText="Button2"
PrimaryButtonClick="ContentDialog_PrimaryButtonClick"
SecondaryButtonClick="ContentDialog_SecondaryButtonClick">

<Grid>
</Grid>
</ContentDialog>

The next thing is to remove the following part from your XAML code:

PrimaryButtonText="Button1"
SecondaryButtonText="Button2"
PrimaryButtonClick="ContentDialog_PrimaryButtonClick"
SecondaryButtonClick="ContentDialog_SecondaryButtonClick"

The trick here starts by removing the default buttons and adding your own buttons (“OK” & “Cancel”) to the ContentDialog. You can style these buttons as you like and use labels apart from “OK” & “Cancel”.

<Grid>
<StackPanel Orientation="Horizontal">
<Button x:Name="OkBtn" Content="OK"></Button>
<Button x:Name="CancelBtn" Content="Cancel" Margin="10,0,0,0"></Button>
</StackPanel>
</Grid>

Next, we want to handle the click events of our buttons, this is where we will set the result of the dialog. The click events of your buttons should look like this:

 public sealed partial class MessageDisplay : ContentDialog
 {
 public MessageDisplay(string message, string title)
 {
 this.InitializeComponent();

 this.Message = message;
 this.MessageTitle = title.ToUpper();
 this.DataContext = this;
 }

 public string Message { get; set; }
 public string MessageTitle { get; set; }

 public ContentDialogResult DiagResult { get; set; }


 private void OkBtn_Click(object sender, RoutedEventArgs e)
 {
 DiagResult = ContentDialogResult.Primary;
 this.Hide();
 }

 private void CancelBtn_Click(object sender, RoutedEventArgs e)
 {
 DiagResult = ContentDialogResult.Secondary;
 this.Hide();
 }

 private void ContentDialog_PrimaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args)
 {
 }

 private void ContentDialog_SecondaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args)
 {
 }
 
 }

In the above code:

  1. We have 3 properties to hold the message to be displayed (Message), the title of the message box (MessageTitle) and the result of the dialog (DiagResult)
  2. When the user clicks OK, we set the result of the dialog to ContentDialogResult.Primary
  3. When the user clicks Cancel, we set the result of the dialog to ContentDialogResult.Secondary

Lastly, We need to show the message box that we’ve just created. We’ll do that like this:

MessageDisplay md = new MessageDisplay("This is to test how the message box displays", "Testing");

md.Closing += (s, args) =>
{
if(md.DiagResult == ContentDialogResult.Primary)
{
//Do something here if the user clicks the "OK" button
}
};

await md.ShowAsync();

The result look like this:

contentdialog_custom

If you feel stuck, you can download my code files here.

In conclusion, you can extend the ContentDialog to suit other purposes such as a login view or other information collection views. If you have any comment or you know a better way to create a custom message box and the use of ContentDialog, kindly drop a comment below. HAPPY CODING!

 

 

December 3, 2016by Oludayo Alli
Programming, Tutorials

Styling the Chart Control in the Silverlight 4 Toolkit

Download source code – 2.41 MB

Introduction

I noticed that many people, including myself, have had some difficulties in styling the Chart control that comes with the Silverlight 4 Toolkit. It is relatively hard to go down the visual tree of the control in order to style the control in the Design view of Expression Blend so as to have a good look and feel. I searched the internet and I got little information on how to go about this process and I decided to work it through myself. I succeeded in restyling the chart control and the majority of the working is done in XAML. I think this article will ease the challenges of other developers/designers facing this same issue.

There are a series of Chart controls that come with the Silverlight 4 Toolkit, and some of these are listed below:

  • BarSeries
  • ColumnSeries
  • StackedColumnSeries
  • BubbleSeries
  • LineSeries
  • PieSeries
  • ScatterSeries

I will be discussing two of these series:

  • ColumnSeries
  • StackedColumnSeries

Note: You can follow the steps in this article both in Expression Blend 4 and Visual Studio 2010, but I will use Expression Blend 4 in this article. If you do not have the toolkit, it is available at Silverlight Toolkit – CodePlex.

ColumnSeries

With a new Silverlight Application created, I added a Chart control and edited the Template. In this article, I decided to delete the Legend and Chart Title from the Template as I will not need them. The Chart Title can still be of use so you can retain yours but the Legend is not useful as we will be using different colors for each column. The chart control now looks like this:

Chart1.png

Next, edit the XAML in order to bind the DependentValueBinding, IndependentValueBinding properties of the Chart control to a class which controls each column. The DataPointStyle property is also bound to a style created to control how the columns look. The XAML is:

<toolkit:Chart x:Name="GasChart" Style="{StaticResource GasChartStyle}" 
    BorderBrush="{x:Null}" Margin="4,141,0,60">
    <toolkit:ColumnSeries 
    DependentValueBinding="{Binding GasValue}" 
    IndependentValueBinding="{Binding GasName}" 
    DataPointStyle="{StaticResource ColorByGradeColumn}" 
    AnimationSequence="FirstToLast"/>
</toolkit:Chart>

The DataPointStyle is set to a StaticResource that sets the ControlTemplate for the ColumnDataPoint. At this point, we’re changing how the columns will look. This look is a gloss-like column compared to the default ugly look. Paying close attention to the XAML code below, you will notice that the Background property of theBorder in the ControlTemplate is bound to one of the properties (GasColor) of a class. This enables changing the column color dynamically:

<Style x:Key="ColorByGradeColumn" TargetType="toolkit:ColumnDataPoint">
    <Setter Property="Background" Value="DarkGray"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="toolkit:ColumnDataPoint">
                <Border  Background="{Binding GasColor}" 
                         BorderBrush="{Binding GasColor}" 
                         BorderThickness="0.5">
                    <Grid Background="{x:Null}">
                        <ToolTipService.ToolTip>
                        <!--Provides the tooltip for each column -->
                            <StackPanel>
                                <ContentControl 
                                  Content ="{ TemplateBinding IndependentValue }"/>
                                <StackPanel Orientation="Horizontal">
                                      <ContentControl 
                                        Content ="{ TemplateBinding 
                                             FormattedDependentValue }"/>
                                    <ContentControl Content ="ppm"/>
                                </StackPanel>
                            </StackPanel>
                        </ToolTipService.ToolTip>
                        <Border BorderBrush="{x:Null}">
                            <Border.Background>
                                <!--This gradiesnt provides 
                                           the gloss-like feature for each-->
                                <LinearGradientBrush EndPoint="1.344,0.5" 
                                          StartPoint="-0.344,0.5">
                                    <GradientStop Color="White" Offset="0"/>
                                    <GradientStop Color="{Binding GasColor}" 
                                          Offset="0.5"/>
                                </LinearGradientBrush>
                            </Border.Background>
                        </Border>
                    </Grid>
                </Border>            
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Now, the class whose properties are bound to the Chart control is:

public class GasNameValue
{
    public double GasValue { get; set; }
    public string GasName { get; set; }
    public Brush GasColor { get; set; }
}

The method below creates new objects of the class above in a List where the values for each column are set. The number of objects created will determine the number of columns that your Chart will contain; most times your data comes from a database or cloud and this process will be dynamic rather than manual. The last line of code sets the ItemsSource of the Chart control to the List object.

private void SetData()
{
    List<GasNameValue> gasList = new List<GasNameValue>
    {
        new GasNameValue
        {
            GasName = "CO2",
            GasValue = 850.0,
            GasColor = new SolidColorBrush(Colors.Red)
        },
        new GasNameValue
        {
            GasName = "SO2",
            GasValue = 700.0,
            GasColor = new SolidColorBrush(Colors.Blue)
        },
        new GasNameValue
        {
            GasName = "CH4",
            GasValue = 820.0,
            GasColor = new SolidColorBrush(Colors.Green)
        },
        new GasNameValue
        {
            GasName = "NO2",
            GasValue = 600.0,
            GasColor = new SolidColorBrush(Colors.Yellow)
        },
        new GasName_Value
        {
            GasName = "F11",
            GasValue = 910.o,
            GasColor = new SolidColorBrush(Colors.Purple)
        },
        new GasNameValue
        {
            GasName = "F12",
            GasValue = 760.0,
            GasColor = new SolidColorBrush(Colors.Orange)
        },
    };
    ((ColumnSeries)GasChart.Series[0]).ItemsSource = gasList;
}

The final ColumnSeries looks like this:

Chart2.png

StackedColumnSeries

The default StackedColumnSeries looks like this (and it looks ugly to me):

Chart4.png

Now, when working with the StackedColumnSeries, after adding the Chart control and editing the Templateas appropriate, you need to add the SeriesDefinition for each Stacked Column. The number ofSeriesDefinitions that you add determines the number of partitions that you will end up having on each Stacked Column. The XAML below consists of six (6) partitions on each Stacked Column with properties bound to a class:

<toolkit:StackedColumnSeries>
    <toolkit:SeriesDefinition
        Title="CO2"
        ItemsSource="{Binding}"
        DependentValueBinding="{Binding GasValue1}" 
        IndependentValueBinding="{Binding Year}"/>
    <toolkit:SeriesDefinition
        Title="SO2"
        ItemsSource="{Binding}"
        DependentValueBinding="{Binding GasValue2}" 
        IndependentValueBinding="{Binding Year}"/>
    <toolkit:SeriesDefinition
        Title="NO2"
        ItemsSource="{Binding}"
        DependentValueBinding="{Binding GasValue3}" 
        IndependentValueBinding="{Binding Year}"/>
        <toolkit:SeriesDefinition
        Title="CH4"
        ItemsSource="{Binding}"
        DependentValueBinding="{Binding GasValue4}" 
        IndependentValueBinding="{Binding Year}"/>
    <toolkit:SeriesDefinition
        Title="F11"
        ItemsSource="{Binding}"
        DependentValueBinding="{Binding GasValue5}" 
        IndependentValueBinding="{Binding Year}"/>
    <toolkit:SeriesDefinition
        Title="F12"
        ItemsSource="{Binding}"
        DependentValueBinding="{Binding GasValue6}" 
        IndependentValueBinding="{Binding Year}"/>
</toolkit:StackedColumnSeries>

This time around, in order to create a new color for each partition, a ResourceDictionaryCollection must be added to the chart palette; this ResourceDictionaryCollection contains six (6) Resource Dictionaries. Each ResourceDictionary provides the color for each partition on a stack. The XAML is like this:

<toolkit:Chart.Palette>
    <toolkit:ResourceDictionaryCollection>
        <ResourceDictionary>
            <Style x:Key="DataPointStyle" TargetType="toolkit:ColumnDataPoint">
                <Setter Property="Background" Value="Red"/>
                <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="toolkit:ColumnDataPoint">
                        <Border Background="Red" BorderBrush="Red" BorderThickness="0.5">
                            <Grid Background="{x:Null}">
                                <ToolTipService.ToolTip>
                                        <StackPanel Orientation="Horizontal">
                                              <ContentControl 
                                              Content ="{ TemplateBinding 
                                                 FormattedDependentValue }"/>
                                            <ContentControl Content =" ppm"/>
                                        </StackPanel>
                                </ToolTipService.ToolTip>
                                <Border BorderBrush="{x:Null}">
                                    <Border.Background>
                                        <LinearGradientBrush EndPoint="1.344,0.5" 
                                            StartPoint="-0.344,0.5">
                                            <GradientStop Color="White" Offset="0"/>
                                            <GradientStop Color="Red" Offset="0.5"/>
                                        </LinearGradientBrush>
                                    </Border.Background>
                                </Border>
                            </Grid>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            </Style>
        </ResourceDictionary>
        <ResourceDictionary>
            <Style x:Key="DataPointStyle" TargetType="Control">
                <Setter Property="Background" Value="Blue"/>
                <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="toolkit:ColumnDataPoint">
                        <Border Background="Blue" 
                              BorderBrush="Blue" BorderThickness="0.5">
                            <Grid Background="{x:Null}">
                                <ToolTipService.ToolTip>
                                        <StackPanel Orientation="Horizontal">
                                              <ContentControl 
                                              Content ="{ TemplateBinding 
                                                  FormattedDependentValue }"/>
                                            <ContentControl Content =" ppm"/>
                                        </StackPanel>
                                </ToolTipService.ToolTip>
                                <Border BorderBrush="{x:Null}">
                                    <Border.Background>
                                        <LinearGradientBrush EndPoint="1.344,0.5" 
                                            StartPoint="-0.344,0.5">
                                            <GradientStop Color="White" Offset="0"/>
                                            <GradientStop Color="Blue" Offset="0.5"/>
                                        </LinearGradientBrush>
                                    </Border.Background>
                                </Border>
                            </Grid>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            </Style>
        </ResourceDictionary>
        <ResourceDictionary>
            <Style x:Key="DataPointStyle" TargetType="Control">
                <Setter Property="Background" Value="Green"/>
                <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="toolkit:ColumnDataPoint">
                        <Border Background="Green" 
                               BorderBrush="Green" BorderThickness="0.5">
                            <Grid Background="{x:Null}">
                                <ToolTipService.ToolTip>
                                        <StackPanel Orientation="Horizontal">
                                              <ContentControl 
                                              Content ="{ TemplateBinding 
                                                   FormattedDependentValue }"/>
                                            <ContentControl Content =" ppm"/>
                                        </StackPanel>
                                </ToolTipService.ToolTip>
                                <Border BorderBrush="{x:Null}">
                                    <Border.Background>
                                        <LinearGradientBrush EndPoint="1.344,0.5" 
                                        StartPoint="-0.344,0.5">
                                            <GradientStop Color="White" Offset="0"/>
                                            <GradientStop Color="Green" Offset="0.5"/>
                                        </LinearGradientBrush>
                                    </Border.Background>
                                </Border>
                            </Grid>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            </Style>
        </ResourceDictionary><ResourceDictionary>
            <Style x:Key="DataPointStyle" TargetType="Control">
                <Setter Property="Background" Value="Yellow"/>
                <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="toolkit:ColumnDataPoint">
                        <Border Background="Yellow" 
                                BorderBrush="Yellow" BorderThickness="0.5">
                            <Grid Background="{x:Null}">
                                <ToolTipService.ToolTip>
                                        <StackPanel Orientation="Horizontal">
                                              <ContentControl 
                                              Content ="{ TemplateBinding 
                                                  FormattedDependentValue }"/>
                                            <ContentControl Content =" ppm"/>
                                        </StackPanel>
                                </ToolTipService.ToolTip>
                                <Border BorderBrush="{x:Null}">
                                    <Border.Background>
                                        <LinearGradientBrush EndPoint="1.344,0.5" 
                                            StartPoint="-0.344,0.5">
                                            <GradientStop Color="White" Offset="0"/>
                                            <GradientStop Color="Yellow" Offset="0.5"/>
                                        </LinearGradientBrush>
                                    </Border.Background>
                                </Border>
                            </Grid>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            </Style>
        </ResourceDictionary>
        <ResourceDictionary>
            <Style x:Key="DataPointStyle" TargetType="Control">
                <Setter Property="Background" Value="Purple"/>
                <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="toolkit:ColumnDataPoint">
                        <Border Background="Purple" 
                              BorderBrush="Purple" BorderThickness="0.5">
                            <Grid Background="{x:Null}">
                                <ToolTipService.ToolTip>
                                        <StackPanel Orientation="Horizontal">
                                              <ContentControl 
                                              Content ="{ TemplateBinding 
                                                FormattedDependentValue }"/>
                                            <ContentControl Content =" ppm"/>
                                        </StackPanel>
                                </ToolTipService.ToolTip>
                                <Border BorderBrush="{x:Null}">
                                    <Border.Background>
                                        <LinearGradientBrush EndPoint="1.344,0.5" 
                                            StartPoint="-0.344,0.5">
                                            <GradientStop Color="White" Offset="0"/>
                                            <GradientStop Color="Purple" Offset="0.5"/>
                                        </LinearGradientBrush>
                                    </Border.Background>
                                </Border>
                            </Grid>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            </Style>
        </ResourceDictionary>
        <ResourceDictionary>
            <Style x:Key="DataPointStyle" TargetType="Control">
                <Setter Property="Background" Value="Orange"/>
                <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="toolkit:ColumnDataPoint">
                        <Border Background="Orange" 
                                 BorderBrush="Orange" 
                                 BorderThickness="0.5">
                            <Grid Background="{x:Null}">
                                <ToolTipService.ToolTip>
                                        <StackPanel Orientation="Horizontal">
                                              <ContentControl 
                                                Content ="{ TemplateBinding 
                                                   FormattedDependentValue }"/>
                                            <ContentControl Content =" ppm"/>
                                        </StackPanel>
                                </ToolTipService.ToolTip>
                                <Border BorderBrush="{x:Null}">
                                    <Border.Background>
                                        <LinearGradientBrush EndPoint="1.344,0.5" 
                                            StartPoint="-0.344,0.5">
                                            <GradientStop Color="White" Offset="0"/>
                                            <GradientStop Color="Orange" Offset="0.5"/>
                                        </LinearGradientBrush>
                                    </Border.Background>
                                </Border>
                            </Grid>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            </Style>
        </ResourceDictionary>
    </toolkit:ResourceDictionaryCollection>
</toolkit:Chart.Palette>

Note that from the above code, the Chart is bound to a class but this time around, the colors are fixed, although it is still possible to dynamically change the colors by databinding the Background properties in theControlTemplate.

The class to which the chart is bound is:

public class GasName_Value
{
    public string Year { get; set; }
    public double GasValue1 { get; set; }
    public double GasValue2 { get; set; }
    public double GasValue3 { get; set; }
    public double GasValue4 { get; set; }
    public double GasValue5 { get; set; }
    public double GasValue6 { get; set; }
}

The final StackedColumnSeries looks like this:

Chart3.png

These techniques can also be applied to other StackedColumn Series such as Stacked100ColumnSeries,StakedBarSeries, and Stacked100BarSeries, with very little manipulations. Happy Styling!

Download source code – 2.41 MB

August 31, 2015by Oludayo Alli
Programming, Tutorials

Creating a custom TimePicker control in WPF 4.0

Download source code – 127 KB

Introduction

I was working on an application, Time Watcher 5.0, and I needed to use a TimePicker control which was not provided along with controls in WPF 4.0. There are several third party TimePicker controls but I was not satisfied with their “mechanism of action and behaviour”. Below are the steps I took to create my own custom TimePicker control knowing that it will benefit a lot of people by sharing the process.

Please note this!

Please note that this is an introductory article on how to create custom controls for your application from a designer’s point of view. This article will give an insight on how to use existing controls to design your own custom controls, and recommendations on how to create reusable custom controls (with registered properties) are provided at the end of this article.

In this demonstration, I’ll be using Expression Blend 4. Now let’s get to business!

Step 1 – Designing the control

In Expression Blend 4, do the following:

Layout

  1. Add a Grid to the LayoutRoot (This is the parent container)
  2. Set the background colour of the Grid to “#000000”
  3. Add a StackPanel to the Grid you just added
  4. Set the orientation to “horizontal”
  5. Set the vertical alignment and horizontal alignment to “stretch”
  6. Add a ToggleButton to the StackPanel

Your layout should look similar to this:

Layout.jpg

Figure 1

ToggleButton – Edit Template

  1. Right click on the ToggleButton and click Edit Template -> Edit a copy.
  2. Select ContentPresenter and cut, select the Chrome, and delete.
  3. Select Template in the Timeline and add a Grid to it from Asset.
  4. Select the Grid and paste the ContentPresenter inside it (your Object and Timeline panel should look like figure 2(a)).
  5. Make sure the Template node is selected in the Timeline.
  6. Go to the Trigger tab, add a new property (see Figure 2b).
  7. Change the property to IsChecked and set the value to “true” (see Figure 2b).
  8. Now select the Grid inside the Template and change the background colour to “#FF919191”.
  9. Return scope to Window.

Figure_2a.jpgFigure_2b.png

Figure 2

Layout – A finishing touch

  1. Rename the ToggleButton to ‘HrBtn‘.
  2. Select the ToggleButton and add a TextBlock to it.
  3. Rename the TextBlock to HrTxt and set the foreground colour to “#FFFFFFFF”.
  4. Select the ToggleButton and copy.
  5. Paste three copies of the ToggleButton inside the StackPanel.
  6. Rename the new copies of the ToggleButton as MinBtn, SecBtn, and AmPmBtn.
  7. Rename the TextBlock inside each ToggleButton as MinTxt, SecTxt, and AmPmTxt.
  8. Add two other TextBlocks to the StackPanel and set their Text property as ‘:’.
  9. Add two Button controls to the StackPanel and rename them as upBtn and downBtn.
  10. Set the Text property of these Button controls to ‘Up’ and ‘Down’, respectively.
  11. Rearrange your timeline to resemble the one shown below:

Timeline.jpg

Your control should look similar to this:

Control.jpg

Step 2 – Coding your control

Under the upBtn_Click Event Handler, add the following code:

/*The code below check to see which node is selected in the control, 
get the current value of the node, increase the value by one 
and display back to the user. This get fired every time the user clicks the 'Up' Button*/

if (HrBtn.IsChecked == true) //If the hour node is selected in the control
{
    int hour = int.Parse(HrTxt.Text); //Converts the Text to an Integer
    
    if (hour == 12)
        hour = hour - hour;
        // This ensures that hour does not exceed
        // 12 since hour ranges from 1 to 12
    
    hour++; //Increase the hour by 1
    
    HrTxt.Text = hour.ToString();
    //Convert the resulting hour back to string format.
}
else if (MinBtn.IsChecked == true) 
{
    int min = int.Parse(MinTxt.Text); //Converts the Text to an Integer
    
    if (min == 59)
        min = -1; //This ensures that minute does not exceed
                  //60 since minute ranges from 0 to 59
    
    min++;
    
    if (min.ToString().Length == 1)
    // This ensures that the minute text maintain a standard length of 2
    {
        MinTxt.Text = "0" + min.ToString();
    }
    else
    {
        MinTxt.Text = min.ToString();
    }
}
else if (SecBtn.IsChecked == true)
{
    int sec = int.Parse(SecTxt.Text);
    
    if (sec == 59)
        sec = -1;
    
    sec++;
    
    if (sec.ToString().Length == 1)
    {
        SecTxt.Text = "0" + sec.ToString();
    }
    else
    {
        SecTxt.Text = sec.ToString();
    }
}
else if (AmPmBtn.IsChecked == true)
{
    //If the Am/Pm node is selected,
    //the code below alternates between Am and Pm.
    if(AmPmTxt.Text == "AM")
    {
        AmPmTxt.Text = "PM";
    }
    else
    {
        AmPmTxt.Text = "AM";
    }
}

Under the downBtn_Click Event Handler, add the following code:

/*The code below check to see which node is selected in the control, 
get the current value of the node, decrease the value by one 
and display back to the user. This get fired every time 
the user clicks the 'Down' Button*/

if (HrBtn.IsChecked == true)
{
    int hour = int.Parse(HrTxt.Text);
    
    if (hour == 1)
        hour = 13;
    
    hour--;
    
    HrTxt.Text = hour.ToString();
}
else if (MinBtn.IsChecked == true)
{
    int min = int.Parse(MinTxt.Text);
    
    if (min == 0)
        min = 60;
    
    min--;
    
    
    if (min.ToString().Length == 1)
    {
        MinTxt.Text = "0" + min.ToString();
    }
    else
    {
        MinTxt.Text = min.ToString();
    }
}
else if (SecBtn.IsChecked == true)
{
    int sec = int.Parse(SecTxt.Text);
    
    if (sec == 0)
        sec = 60;
    
    sec--;
    
    
    if (sec.ToString().Length == 1)
    {
        SecTxt.Text = "0" + sec.ToString();
    }
    else
    {
        SecTxt.Text = sec.ToString();
    }
}
else if (AmPmBtn.IsChecked == true)
{
    if(AmPmTxt.Text == "AM")
    {
        AmPmTxt.Text = "PM";
    }
    else
    {
        AmPmTxt.Text = "AM";
    }
}

If you have good hands in design especially in Expression Blend, you can skin your control as it suits you. The final control of Time Watcher 5.0 application looks like this:

Final.jpg

On a final note

When creating a reusable control, it must be “skinable”; the use of the WPF commanding model (see Commanding Overview) is also better than raising clicked events if you are creating a control for reuse. A bindable DateTime or TimeSpan property will also enable users of this control to bind to it.

Recommendations

For further readings on how to create a custom control and add dependency properties, I recommend Create a WPF Custom Control, Part 1 and Create a WPF Custom Control, Part 2 by David Veeneman.

Download source code – 127 KB

August 31, 2015by Oludayo Alli
Page 2 of 2«12

Get Notification For New Content

Avatars by Sterling Adventures