Data Converstion and Task Addition with WPF

Welcome to the third part of a four-part series that explains WPF through an example. We're now deep into the process of building our to-do list application. We need to make it possible for someone using the application to check off tasks when they are done, and add new tasks. Keep reading to learn how we do this.

Contributed by
Rating: 5 stars5 stars5 stars5 stars5 stars / 1
September 08, 2008
Rate this Article:
MEH MEH++


SEARCH ASP FREE
TOOLS YOU CAN USE

advertisement

Converting Values

So, we have a CheckBox that needs to be checked or unchecked depending on whether the task is done or not done, and we have a TextBlock that needs to be colored according to the task's priority. The CheckBox contains a property called IsChecked, which is a boolean indicating whether or not the box is checked, but the XML simply contains a "Yes" or "No" string. Similarly, the TextBlock contains a Foreground property to set the color, but priority in the XML file is indicated by "Low," "Medium" or "High." We're going to have to convert the values in the XML to the correct property values, and, for the CheckBox, we need a way to convert the value of IsChecked back into a string for when the user marks a task as done.

Conversion is done by creating a class that implements the IValueConverter interface and providing the proper code for conversion between the data source and the appropriate controls. Fortunately, this interface isn't very complicated, and not a lot of code will be required. The interface calls for two methods: Convert and ConvertBack. The Convert method is called when a value is taken from the data source, and the ConvertBack method is called when a value needs to be put back into the data source.

Let's create a converter class for the CheckBox first. Create a new class in Visual Studio called StatusConverter. Create the class, implementing IValueConverter:


namespace WpfToDo

{

 class StatusConverter : System.Windows.Data.IValueConverter

{

}

}


Next, we need to implement the Convert method. The Convert method takes several parameters, but only the first one is important here, since it contains the actual value that we need to convert. Remember that we'll be accepting a "Yes" or "No" string from the XML file and will need to return a boolean. This conversion can be done in a single step:


public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)

{

 return ((string)value).ToLower() == "yes";

}


Above, the incoming string is converted to lower case. That way, the content of the Status element can be case insensitive.

Converting the boolean back into a string is also very simple:


public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)

{

 if ((bool)value)

{

 return "Yes";

}

 return "No";

}

Converting Values, Continued

Now the converter for status is done, and it's time to move on to the converter for priority. The converter needs to convert the priority into an appropriate color name: red for high priority, orange for medium priority, and green for low priority. The process is exactly the same as before, only there's no need to be able to convert back (since there's no way to convert back from within the application-the color is static). Create a class named PriorityConverter:


namespace WpfToDo

{

 class PriorityConverter : System.Windows.Data.IValueConverter

{

 public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)

{

 string rawPriority = ((string)value).ToLower();

 if (rawPriority == "high")

{

 return "Red";

}

 else if (rawPriority == "medium")

{

 return "Orange";

}

 else

{

 return "Green";

}

}


 public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)

{

 throw new NotImplementedException();

}


}

}


So, the application contains some two classes that were coded in, but that code now needs to be referenced in the XAML. Fortunately, however, the intermediate work involved in making this possible is very simple. First, the WpfToDo namespace, which contains the two classes, needs to be worked into the XAML. Place the following attribute in the Window tag:


xmlns:local="clr-namespace:WpfToDo"


You'll find several similar attributes already there. Place the new one right under them.

Next, instances of each of the classes need to be placed in the Resources section, just like the XmlDataProvider:


<Window.Resources>

 ...

 <local:StatusConverter x:Key="statusConverter" />

 <local:PriorityConverter x:Key="priorityConverter" />

 ...

</Window.Resources>


The final step is very simple. The binding needs to be set up, along with references to the two converters. Modify the existing tags, adding the appropriate attributes:


<CheckBox Grid.Row="0" Grid.RowSpan="2" Grid.Column="0" HorizontalAlignment="Center" VerticalAlignment="Center" IsChecked="{Binding XPath=Done, Converter={StaticResource statusConverter}}" />

<TextBlock Grid.Row="0" Grid.Column="1" FontWeight="Bold" Foreground="{Binding XPath=Priority, Converter={StaticResource priorityConverter}}" Text="{Binding XPath=Name}" />


The application now represents the data fully:



Adding Tasks

We now need to create a way to add tasks to the list. The easiest way to do this is to create an "Add Task" dialog that's shown when the user clicks the "Add Task" button. The dialog will prompt the user for the required information (title, priority and description), and when the "Okay" button is clicked, the new task will be added to the list.

The dialog will require a new window. Add a new Window (WPF) to the project called AddTaskDialog.xaml. Visual Studio will then create the basic XAML for the window. The default height of the new window is too big for our needs, so we'll need to decrease it a bit. The title should also be changed to something more appropriate:


<Window x:Class="WpfToDo.AddTaskDialog"

 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

  Title="Add Task" Height="250" Width="300">


Next, the dialog needs some controls. For the title, a TextBox control will do; for the priority, a ComboBox control will do; and for the description, a TextBox control with wrapping will do. These input controls will need labels. Two buttons will also be necessary, an "Okay" button and a "Cancel" button.


It's best that the controls be organized into a grid of five rows and three columns in order to achieve a look like this (the grid lines are shown by setting the ShowGridLines attribute of Grid to True):



I'll go ahead and place all the required XAML below. Most of it should be familiar to you, and so I'll only explain a few parts in bold:


<Grid HorizontalAlignment="Center" VerticalAlignment="Center">

 <Grid.RowDefinitions>

 <RowDefinition Height="25" />

 <RowDefinition Height="25" />

 <RowDefinition Height="25" />

 <RowDefinition Height="100" />

 <RowDefinition Height="25" />

 </Grid.RowDefinitions>

 <Grid.ColumnDefinitions>

 <ColumnDefinition Width="75" />

 <ColumnDefinition Width="75" />

 <ColumnDefinition Width="125" />

 </Grid.ColumnDefinitions>

 

 <Label Grid.Row="0" Grid.Column="0" Content="Title:" />

 <TextBox Name="TaskTitle" Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="2" />

 <Label Grid.Row="1" Grid.Column="0" Content="Priority:" Margin="0,3,0,0" />

 <ComboBox Name="TaskPriority" Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" SelectedIndex="0" Margin="0,3,0,0">

 <ComboBoxItem Foreground="Green">Low</ComboBoxItem>

 <ComboBoxItem Foreground="Orange">Medium</ComboBoxItem>

 <ComboBoxItem Foreground="Red">High</ComboBoxItem>

 </ComboBox>

 <Label Grid.Row="2" Grid.Column="0" Content="Description:" Margin="0,3,0,0" />

 <TextBox Name="TaskDescription" Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="3" TextWrapping="Wrap" Margin="0,3,0,0" />

 <Button Name="OkayButton" Grid.Row="4" Grid.Column="0" Content="Okay" Margin="0,3,2,0" />

 <Button Name="CancelButton" Grid.Row="4" Grid.Column="1" IsCancel="True" Content="Cancel" Margin="2,3,0,0" />

</Grid>


The ComboBox control is pretty simple to understand, but it's nonetheless new and merits being pointed out. Notice how the priorities are colored as they are in the task list itself.

In order to wrap text in the description TextBox, the TextWrapping attribute is set to Wrap.

The IsCancel attribute of the cancel button is set to True. This way, if the user presses escape, the button will automatically be "clicked."

Next, the dialog needs to respond to the okay button being clicked. If the button is clicked, then the window's DialogResult property must be set to true. This will close the dialog and return true (as described below). Either double click the button in the designer or add an event handler through XAML:


<Button Name="OkayButton" Grid.Row="4" Grid.Column="0" Content="Okay" Margin="0,3,2,0" Click="OkayButton_Click" />


The event handler operates exactly as described above:


private void OkayButton_Click(object sender, RoutedEventArgs e)

{

DialogResult = true;

}


Adding Tasks, Continued

Now that the dialog is set up, it's time to make it all work. This is actually really simple. Back in Window1, either double click the "Add Task" button in the designer to create an event handler, or add it manually through XAML:


<Button Name="AddButton" Grid.Row="1" Grid.Column="0" Margin="0,3,2,0" Content="Add Task" Click="AddButton_Click" />


In the event handler, we need to create an instance of AddTaskDialog and call it as a dialog using the ShowDialog method. This will return a boolean value like a normal dialog does. If True is returned (that is, if the user gives the application the okay to actually add a new task), then a task needs to be added to the ListBox.

To do this, we need to convert all of the data into an XML element (represented by the XmlElement class) and stick it into the XmlDataProvider. Open up the code-behind for Window1 (Window1.xaml.cs). We're going to be using various classes in the System.Xml namespace, so go ahead and add a using directive:


using System.Xml;


Most of the code relates to XML rather than WPF, so there's no need to explain anything, except for one method in bold:


private void AddButton_Click(object sender, RoutedEventArgs e)

{

 AddTaskDialog dlg = new AddTaskDialog();

 if (dlg.ShowDialog() == true)

{

 // Get the document

 XmlDocument document = ((XmlDataProvider)FindResource("tasks")).Document;


 // Create the Task element

 XmlElement task = document.CreateElement("Task");


 // Create the Name element

 XmlElement name = document.CreateElement("Name");

name.InnerText = dlg.TaskTitle.Text;

task.AppendChild(name);


 // Create the Priority element

 XmlElement priority = document.CreateElement("Priority");

priority.InnerText = dlg.TaskPriority.Text;

task.AppendChild(priority);


 // Create the Done element

 XmlElement done = document.CreateElement("Done");

done.InnerText = "No";

task.AppendChild(done);


 // Create the Description element

 XmlElement description = document.CreateElement("Description");

description.InnerText = dlg.TaskDescription.Text;

task.AppendChild(description);


document.DocumentElement.AppendChild(task);

}

}


The FindResource method does as its name implies: it obtains a reference to a resource defined in XAML. Note that the result must then be cast into the proper type.

Next week, we will finish building our application. You won't want to miss it.

blog comments powered by Disqus
WINDOWS SCRIPTING ARTICLES

- More Windows Scripting Workarounds from Nilpo
- Overloading Methods and More in VBScript
- Improving MFC for Windows Vista
- Regular Expressions in VBScript
- Working with Dates in WMI
- Completing Calendars with VBScript Date Func...
- Building Calendars with VBScript Date Functi...
- Working With Dates and Times in VBScript
- Designing WCF DataContract Classes Using the...
- Understanding Dates and Times in VBScript
- Working With Arrays in VBScript
- Compressed Folders in WSH
- Using .NET Interops in VBScript
- Nilpo`s Scripting Secrets, Vol I
- Database operations using Silverlight 2.0 WC...

ASP Web Hosting ASP.Net Web Hosting Windows Web Hosting
 
 
 

ASP Free Forums 
 RSS  Tutorials RSS
 RSS  Forums RSS
 RSS  All Feeds
Site Map 
Request Media Kit
Write For Us Get Paid 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
Privacy Policy 
Support 


© 2003-2012 by Developer Shed. All rights reserved. DS Cluster 3 - Follow our Sitemap
Most Popular Topics
All ASP.Net Tutorials