top button
Flag Notify
    Connect to us
      Site Registration

Site Registration

How to Changing the Foreground Colour of an XAML Control Using a Binding Convertor?

+2 votes
756 views
 

The great thing about XAML is that you can easily change the foreground colour of controls, such as a TextBlock, to be exactly what you want it to be. Whether that is through the built-in colour names or a HEX colour is completely your choice.

 

However there may be times when you simply wish to change the colour of a control dependent on the value that it is displaying. In this example we will be using a TextBlock that has it's Text value assigned to it using data context binding.

 

MainPage.xaml

<Page        
    x:Class="MainPage"    
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"    
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"    
    xmlns:local="using:TestProject"    
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"    
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"        
    mc:Ignorable="d">    
    <Page.Resources>    
        <DataTemplate x:Key="listViewItems">    
            <StackPanel>    
                <TextBlock        
                    Margin="5,5,5,5"        
                    Text="{Binding Name}"        
                    Style="{StaticResource BaseTextBlockStyle}"/>    
                <TextBlock        
                    Margin="5,5,5,5"        
                    Text="{Binding Ripeness}"        
                    Style="{StaticResource BaseTextBlockStyle}"/>    
            </StackPanel>    
        </DataTemplate>    
    </Page.Resources>    
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">    
        <ListView        
            x:Name="listViewTest"        
            Margin="5,5,5,5"        
            VerticalAlignment="Center"        
            HorizontalAlignment="Center"        
            ItemsSource="{Binding}"        
            SelectionMode="None"        
            IsItemClickEnabled="False"        
            ItemTemplate="{StaticResource listViewItems}"        
            ContainerContentChanging="listViewUpdated"></ListView>    
        <TextBlock        
            x:Name="listViewNoItems"        
            Margin="5,5,5,5"        
            VerticalAlignment="Center"        
            HorizontalAlignment="Center"        
            Text="There are no fruits in your list to display!"        
            Style="{StaticResource BaseTextBlockStyle}"        
            Visibility="Collapsed"/>    
        <Button        
            Width="150"        
            Height="50"        
            Margin="20"        
            VerticalAlignment="Center"        
            HorizontalAlignment="Right"        
            Content="Clear fruit"        
            Click="clearFruitBasket"/>    
    </Grid>    
</Page>  

 

MainPage.xaml.cs


using System.Collections.ObjectModel;    
using Windows.UI.Xaml;    
using Windows.UI.Xaml.Controls;    
namespace CSharpCornerTestProject     
{    
    public class Fruit     
    {    
        public string Name    
        {    
            get;    
            set;    
        }    
        public string Ripeness     
        {    
            get;    
            set;    
        }    
    }    
    public sealed partial class MainPage: Page     
    {    
        private ObservableCollection < Fruit > fruitList = new ObservableCollection < Fruit > ();    
        public MainPage()     
        {    
            this.InitializeComponent();    
            fruitList.Add(new Fruit()    
            {    
                Name = "Apple", Ripeness = "Ok"    
            });    
            fruitList.Add(new Fruit()    
            {    
                Name = "Banana", Ripeness = "Bad"    
            });    
            fruitList.Add(new Fruit()    
            {    
                Name = "Kiwi", Ripeness = "Rotten"    
            });    
    
            listViewTest.ItemsSource = fruitList;    
        }    
        private void listViewUpdated(ListViewBase sender, ContainerContentChangingEventArgs args) {    
            if (listViewTest.Items.Count == 0)     
            {    
                listViewNoItems.Visibility = Visibility.Visible;    
                listViewTest.Visibility = Visibility.Collapsed;    
            }     
            else     
            {    
                listViewNoItems.Visibility = Visibility.Collapsed;    
                listViewTest.Visibility = Visibility.Visible;    
            }    
           }    
        private void clearFruitBasket(object sender, RoutedEventArgs e)    
        {    
            // clear the fruit list!        
            if (fruitList != null) fruitList.Clear();    
        }    
    }    
}

As I stated above, this is the code base that we used in my previous article about displaying a message once a ListView control no longer has any items in it. We will slightly modify this now so that the ripeness of the fruit in our fruit basket is colour-coded depending on its value.

 

The first thing we need to do is to create a convertor class for us to use when binding data to the list view. This is a very simple affair and just requires you to add a new "Class file" to your project.

 

FruitBasketConvertor.cs

using System;    
using Windows.UI;    
using Windows.UI.Xaml.Data;    
using Windows.UI.Xaml.Media;    
namespace CSharpCornerTestProject.Convertors     
{    
    public class fruitBasketRipenessForegroundConvertor: IValueConverter    
    {    
        public object Convert(object value, Type targetType, object parameter, string language)    
        {    
            string ripeness = (value as string);    
            if (ripeness == "Ok") return new SolidColorBrush(Colors.ForestGreen);    
            else if (ripeness == "Bad") return new SolidColorBrush(Colors.OrangeRed);    
            else if (ripeness == "Rotten") return new SolidColorBrush(Colors.DarkRed);    
            // default return value of lime green      
            return new SolidColorBrush(Colors.LimeGreen);    
        }    
        public object ConvertBack(object value, Type targetType, object parameter, string language)    
        {    
            throw new NotImplementedException();    
        }    
    }    
}  

That is all there is to our file, just those 30 lines. Do take note, however, that we have placed the convertors under their own namespace, CSharpCornerTestProject.Convertors.

 

Using convertors isn't all as daunting as it seems. You create your own custom class, making sure that it derives from IValueConvertor.  Then all we need are two functions.

public object Convert(object value, Type targetType, object parameter, string language)  
{  
    // your convertor code goes here    
}  
public object ConvertBack(object value, Type targetType, object parameter, string language)   
{  
    // your convert back code goes here    
}

The Convert function takes the raw value of your binding and allows you to access anything associated with that, whether it is a class, a string, or anything of your choosing.

 

The ConvertBack function is generally not used all that often and so in our example we are leaving it asthrow new NotImplementedException();. Its main use would be if you wanted to convert the value back to its original state.

 

Returning to the Convert function, this is very simple and there isn't all that much to it at all. All we do here is take the object value and store it into our string variable, ripeness.  

public object Convert(object value, Type targetType, object parameter, string language)   
{  
    string ripeness = (value as string);  
    if (ripeness == "Ok") return new SolidColorBrush(Colors.ForestGreen);  
    else if (ripeness == "Bad") return new SolidColorBrush(Colors.OrangeRed);  
    else if (ripeness == "Rotten") return new SolidColorBrush(Colors.DarkRed);  
    // default return value of lime green      
    return new SolidColorBrush(Colors.LimeGreen);  
}   

Since we have different forms of Ripeness in our Fruit class, we have three separate if statements to determine which colour we should return for our Foreground colour.

 

When converting a Foreground (or Background) XAML member, it expects a SolidColorBrush to be returned and so that is what we are giving it.

 

That is everything that we need to do for the code side of things with our convertor, the next step is much simpler and only requires us to add three new lines of code to the existing MainPage.xaml file that we have.

 

In our Page control, we need to add a new member, highlighted in bold Green.

<Page  
x:Class="MainPage"  
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
    xmlns:local="using:rTestProject"  
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"  
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"  
    xmlns:utils="using:TestProject.Convertors"  
mc:Ignorable="d">  

This will allow us to access the custom convertor class that we just created in FruitBasketConvertor.cs.

 

Now that we have done that, we need to add our convertor function as a page resource and provide it a key. This will allow us to access it when using the binding convertor. Once again, the addition is highlighted in bold Green.

<Page.Resources>  
    <utils:fruitBasketRipenessForegroundConvertor x:Key="ripenessConvertor"/>  
    <DataTemplate x:Key="listViewItems">  
        <StackPanel>  
            <TextBlock      
                Margin="5,5,5,5"      
                Text="{Binding Name}"      
                Style="{StaticResource BaseTextBlockStyle}"/>  
            <TextBlock      
                Margin="5,5,5,5"      
                Text="{Binding Ripeness}"      
                Style="{StaticResource BaseTextBlockStyle}"/>  
        </StackPanel>  
    </DataTemplate>  
</Page.Resources>

Now that we have given our convertor a key, we can access it anywhere in the MainPage.xaml file when we are binding items. We just have one last thing to do now, that is to add a Foreground member to the TextBlock control that is telling us how ripe our fruit is.

<TextBlock    
    Foreground="{Binding Ripeness, Converter={StaticResource ripenessConvertor}}"    
    Margin="5,5,5,5"    
    Text="{Binding Ripeness}"    
    Style="{StaticResource BaseTextBlockStyle}"/>    

That is everything that we need to do to start dynamically changing the foreground colour of our XAML controls dependent on what the value they're displaying is. If you run the app your fruit basket should now show the Ripeness of each fruit in the three different colours that we assigned earlier on whilst creating our convertor function.

 

posted Feb 29, 2016 by Jdk

  Promote This Article
Facebook Share Button Twitter Share Button LinkedIn Share Button


Related Articles

In this article, I will try to make a representation of the Grid object witch is directly derived from the Panel abstract class and we can say that is a flexible area that contains rows and columns, it plays a role of container in a given WPF window. The grid could be found in the PresentationFramework assembly. The grid control could be used to create a complex layout that gives to the application an attractive and ergonomic look. So let's discover how to configure it using XAML in this part and in second part I will illustrate how to perform the same task using the code behind, I mean C#.

At first look, when a new WPF application is defined, we have the impression that there is not controls but the window one, even if the "<Grid></Grid>" tags are presents, and the first question that one can ask is where are the grid lines if it is a grid really? 

 

Figure 1

I tell you ok try this code:

<Grid ShowGridLines="True">

        <Grid.RowDefinitions>

            <RowDefinition></RowDefinition>

            <RowDefinition></RowDefinition>

            <RowDefinition></RowDefinition>

        </Grid.RowDefinitions>

        <Grid.ColumnDefinitions>

            <ColumnDefinition></ColumnDefinition>

            <ColumnDefinition></ColumnDefinition>

            <ColumnDefinition></ColumnDefinition>

        </Grid.ColumnDefinitions>       

    </Grid>

I use the <Grid.RowDefinitions> to define a collection of rows and a<Grid.ColumnDefinitions> to define columns collection. In the other hand I use<RowDefinition> to define a row element within the grid control and <ColumnDefinition> to define a column element, and then I set ShowGridLines property to true, it is very important in order to render columns and rows visible. The result will be as follows:

Figure 2

The columns and rows definition mode could be, namely star, Auto or Pixel.

The Star definition

It means that the related size could be expressed as weighted proportion of available space, for example if a size of a given first row is double of a second given row size, then the first one will receive two units of the entire grid size, meanwhile, the second one will have one unit as size. Rows and columns sizes are expressed by this symbol * that represents a unit of size. The XAML code sample illustrates how to define a size based on star definition.

<Grid ShowGridLines="True" >

        <Grid.RowDefinitions>

            <RowDefinition></RowDefinition>

            <RowDefinition></RowDefinition>

            <RowDefinition></RowDefinition>

        </Grid.RowDefinitions>

        <Grid.ColumnDefinitions>

            <ColumnDefinition Width="2*"></ColumnDefinition>

            <ColumnDefinition></ColumnDefinition>

            <ColumnDefinition></ColumnDefinition>

        </Grid.ColumnDefinitions>       

    </Grid>

The result of the above code is:

Figure 3

The above code sets the first column width as double of the reset of the columns.

The Pixel definition

It means that the size is defined in terms of pixels such as in the ASP applications. This bellow code illustrate how to define a dimension of a given column or row based on pixels

<Grid ShowGridLines="True" >

        <Grid.RowDefinitions>

            <RowDefinition></RowDefinition>

            <RowDefinition></RowDefinition>

            <RowDefinition></RowDefinition>

        </Grid.RowDefinitions>

        <Grid.ColumnDefinitions>

            <ColumnDefinition Width="100px"></ColumnDefinition>

            <ColumnDefinition></ColumnDefinition>

            <ColumnDefinition></ColumnDefinition>

        </Grid.ColumnDefinitions>       

    </Grid>

And this is a presentation of what could be if such alternative is used

Figure 4

The Auto definition

It means that the size is proportional to the content object size. Once the column or the row width or height is set to auto and there is no object contained with it. It disappears from the grid but it doesn't mean that it is deleted. If you add controls within, it takes exactly the control dimension. For example, if we make a rectification of the previous code

<Grid ShowGridLines="True" >

        <Grid.RowDefinitions>

            <RowDefinition></RowDefinition>

            <RowDefinition></RowDefinition>

            <RowDefinition></RowDefinition>

        </Grid.RowDefinitions>

        <Grid.ColumnDefinitions>

            <ColumnDefinition Width="Auto"></ColumnDefinition>

            <ColumnDefinition></ColumnDefinition>

            <ColumnDefinition></ColumnDefinition>

        </Grid.ColumnDefinitions>       

    </Grid>

The grid appearance will be

Figure 5

Cut  Width="Auto"  then drag and drop a button into the grid and make sure that it is contained within the row 0 , column 0 grid cellule and this is the XAML button code.

<Button Grid.Column="0" Grid.Row="0" Width="100" Name="button1">Button</Button>

Now, paste Width="Auto" exactly in its previous place and you will observe this. As you see the button is clipped rather that scrolled.

Figure 6

 

READ MORE

Data binding is that robust way to connect your properties with any data source. In this tutorial we will dig into class binding step-by-step. If you are already familiar with class binding then you can skip this tutorial.

Class Binding

Class Binding provides high-level access to the definition of a binding that connects the properties of the binding target objects and any data source (for example, a database, an XML file, or any object that contains data). It is so strong and easy that one can easily interact with data within the application and can bind the data with any of the properties of the objects.

Let's Dig

To understand class binding we will go through the following procedure for easy comprehension. First we will create a simple Windows 8.1 Silverlight application. This application will show the data of the object bound with the items of the Listbox.

blank app
Fig:1. Creating the Project.

Give the project a good name. Once you have created the project, you will see the following screen:

create project

Now for the class binding, we will create a class first, in this case I will create a class named Country:

class name country

We will add some Plain Old CLR Objects (POCOs) to our class:

class

After creating the class, we will move the MainPage.xaml and will add the Listbox to the Content Panel as in the following:

main page

Then, it would be noteworthy to specify how to customize the items in the listbox, so customizing the listbox item Template and as our class has three data members, we will add three controls to each item, in this case I will use two textblocks and one checkbox for the bool data member.



You can see in this figure that the checkbox and the textblocks are being bound with the data members of the class (Country), so basically the XAML code that actually binds the class is as in the following:

  1. <CheckBox IsChecked="{Binding IsMember}"/>  
  2. <TextBlock Grid.Column="1" Name="CountryName" Text="{Binding CountryName}"/>  
  3. <TextBlock Grid.Column="2" Name="txtShortName" Text="{Binding ShortName}"/>   

Now to load some dummy data into the Country class we will create the load event and add some data on the load event of the Page, for that we will need to create the list and add some objects of class Country to that list and then make this list the source for the listbox. Here is the C# code of that:

cs code

And now you can run the project, we are done with the simple class binding.

demo

READ MORE

Introduction


Figure 1: 
SpiltView Navigation Framework

The very idea of SpiltView originates from the Navigation Framework inside a XAML application. The navigation framework was introduced with Silverlight. The major components of the Navigation Framework were:

  1. Frame
  2. Page

The Frame here is much like the browser that was used to contain a page that can be navigated back and forth. Here, the frontward stack and the backward stack.

They supported a series of methods, namely:

  1. GoBack()
  2. GoForward()
  3. CanGoBack()
  4. CanGoForward()

But often it's only about the navigation that the developers are concerned about. This is why you have SplitView. SplitView helps us to navigate by “type” and not the URI that we used to do in Silverlight. Also, we don't need to care about the physical location of the file as well. 

The Page 

The page has the following two methods:

  1. OnNavigatedTo(Param)
  2. OnNavigatedFrom()

These two overridden methods help to navigate and hence help us to interact with the page.

Although there are a few more things worth noticing in Page.NavigationCacheMode that are primarily concerned with whether the page is supposed to be created again or the same instance of the page will be rendered.

Jumping with SpitView

SplitView is there for navigation. That means this gives a smoother way to navigate with menus and making the UI smoother and more fluid. 

Where to use a SpiltView



Figure 2: 
SpiltView Usage

Universally this is also know as the “Hamburger Menu” because it has two pieces of bread forming a nice Big Boy burger. But yes, that’s the split view. It’s a menu that takes care of a tons of problems a developer has while transiting from one page to another or simply just navigating from one part of the app to another. 

Behaviors of a SplitView



Figure 3: 
Behaviors of a SplitView

A SplitView when it is tapped pops out a menu and shows various options. Although it's not a requirement to have the Split View respond to a tap request.

Where to get the SplitView from



Figure 4: 
Font Selection

The new Segoe Font will have the SplitView. All these are vectors and are oriented to the Windows 10 Style.

Application of the SplitView

A SplitView namely has the following 2 things:

  • SplitView.Pane
  • SplitView.Content

Details

Let's talk in details about SplitView.Pane.



Figure 5: SplitView Pane

A Pane is where the developer puts in all the buttons that are either on the left or the right of the application. The Pane will also takes the kinds of buttons that will be available for tapping in the application.

The SplitView.Content



Figure 6: 
SplitView Content

The most important property is the Content property. The Content Property sits over the frame and gives a navigation affordance. The Content also gives us a lot of grip with the overlay on the UI. 

The SplitView.PaneDisplayMode

Depending on whether the SplitView is open or closed we have the PaneDisplayMode as its property.



Figure 7: PaneDisplayMode Properties

The Inline, when set to true, will provide a jolting experience to the user since the content will shift the SplitView opened up. In case of the overlay although the content will not shift, it will simply have the splitview menu coming out as a flyer over the content. The CompactInline will have the capabilities of shifting the content to a large extent if the SplitView is set to true or just have a sleek thin outline when set to false. The Compact overlay will have the same properties like the overlay only difference is in both of the cases of a Compact Overlay there will be a slight shift of content.

READ MORE

Data Binding

Data Binding is the process of taking some data and associating it to visual elements on user interface (UI).

Overview of Data Binding

We will take any object and with their properties present each instance of object in collection on screen to user in “Grid “like fashion. We get to create a little template of how each individual instance of object is represented in the user interface .The “ListView” is also same but it works in single column fashion.

Create a Project in Visual Studio 2015

In order to perform data binding , you need to create a project in Visual Studio 2015, steps are simple:

  1. Select “Universal” as shown by arrow.
  2. Select “Blank App” as shown in circle.
  3. Name your solution, for instance “BindDataExample“.

binddataexample

Designer Window

A designer window will open once you create the project with name”MainPage.xaml“. in this window there is a designer surface and you can also write your XAML code …now for instance we select our object a “Book” and in order to perform data binding simply create a user interface in XAML . The code is shown in the following image in rectangle sharpe.

Designer Window

Create Data Model

  1. Go to “Solution Explorer” shown by circle.
  2. Right click the “BindDataExample” shown by arrow.
  3. Add new folder, name it “Models” shown by circle.

Create Data Model

Create C# class in Models Folder

  1. Go to Models folder.
  2. Right click and select add new item.
  3. Select Class and name it “Book.cs“.

C# class

Book Class with Properties

Once you perform all the above mentioned tasks, there will be a c# class open for us and our object which in this case is a book, we can create its class and define its properties in that very C# class we have.

  1. Create a class “Book“.
  2. Define its properties.
  3. Copy the C# code in red rectangular box.

Book

Creating New Instances & Add in Collection

After you created your Book class and set its properties, now its time to create instances of your class and populate it into a collection, list of book. We will generate another class , name it “BookManager” in the same file, for this purpose. And then return the list to caller. The following code will help you out.

BookManager

Add GridView, Bind to data from BookManager Class

Our next step is after we created the instances, storing them in collection is to bind the data in GridView from that very class. For this we will return to our “MainPage.xaml” and create a template that how each individual item will appear on the screen. The template code is in red box . 

MainPage.xaml

Add XAML namespace

In order to reference the class in XAML, we need to reference its namespace in XAML. Here you go, shown by red arrow.

xaml namespace

Create Public Property in MainPage.xaml.cs

After we create the template, our next step will be to create a public property in “mainpage.xaml.cs “and populate it with Books.

  1. Add public property as shown in circular region.
  2. Make sure you add a namespace if it is not there as shown by arrow.
  3. Initialize it with “Books=BookManager.GetBooks();.”, this will return list of books.

public property

Run your Application.

After completion of all the steps, run you application and the final result will be shown something like the following,

bind your application

Working on Alignment

You can change the alignment and margin again. Here's a simple step to do,

Alignment

Overview

In nutshell, the alignment will make display much better.

READ MORE

We can use the Arc XAML element to draw arcs in XAML. Besides drawing arcs using the Arc element, we can also use the ArcSegment element. The ArcSegment is useful when an arc becomes a part of a graphics path or a larger geometric object.

 

In this article, we will see how to use the ArcSegment to draw arcs in XAML and WPF.

 

The ArcSegment object represents an elliptical arc between two points. The ArcSegment class has the five properties Point, Size, SweepDirection, IsLargeArc and RotationAngle. 

 

  • The Point property represents the endpoints of an arc. 
  • The Size property represents the x and y radiuses of an arc. 
  • The SweepDirection property specifies whether an arc sweep direction is clock wise or counter clock wise. 
  • The IsLargeArc property returns true if an arc is greater than 180 degrees. 
  • The RotationAngle property represents the angle by which an ellipse is rotated about the x-axis.

 

 

The following figure provided by the MSDN documentation shows these property values and their results.

Graphics-Arc.jpg

<ArcSegment Size="300,50" RotationAngle="30" 
            IsLargeArc="True" SweepDirection="CounterClockwise"  Point="200,100" />

A Path object is used to draw an arc by setting a PathGeomerty as Path.Data. The following code snippet creates a Path and sets a ArcSegment as a part of PathFigure.Segments.

<Path Stroke="Black" StrokeThickness="1">
    <Path.Data>
        <PathGeometry>
            <PathGeometry.Figures>
                <PathFigureCollection>
                    <PathFigure StartPoint="0,100">
                        <PathFigure.Segments>
                            <PathSegmentCollection>
                                <ArcSegment Size="300,50" RotationAngle="30"
                                            IsLargeArc="True"
                                            SweepDirection="CounterClockwise"
                                            Point="200,100" />
                            </PathSegmentCollection>
                        </PathFigure.Segments>
                    </PathFigure>
                </PathFigureCollection>
            </PathGeometry.Figures>
        </PathGeometry>
    </Path.Data>
</Path>

The output looks like Figure 1.

 

ArcSegment-1.jpg

Figure 1

We can paint an arc by simply painting the path using the Fill method. The following code snippet has changes in it from the previous code that fills a path. 

<Path Stroke="Black" StrokeThickness="1" Fill="Yellow">

The new output looks like Figure 2.

 

ArcSegment-Filled.jpg

Figure 2

The following code snippet creates an arc segment shown in Figure 2 dynamically.

private void CreateArcSegment()
{
    PathFigure pthFigure = new PathFigure();
    pthFigure.StartPoint = new Point(0, 100); 

    ArcSegment arcSeg = new ArcSegment();
    arcSeg.Point = new Point(200, 100);
    arcSeg.Size = new Size(300,50);
    arcSeg.IsLargeArc = true;
    arcSeg.SweepDirection = SweepDirection.Counterclockwise;
    arcSeg.RotationAngle = 30;   

    PathSegmentCollection myPathSegmentCollection = new PathSegmentCollection();
    myPathSegmentCollection.Add(arcSeg); 

    pthFigure.Segments = myPathSegmentCollection; 

    PathFigureCollection pthFigureCollection = new PathFigureCollection();
    pthFigureCollection.Add(pthFigure); 

    PathGeometry pthGeometry = new PathGeometry();
    pthGeometry.Figures = pthFigureCollection; 

    Path arcPath = new Path();
    arcPath.Stroke = new SolidColorBrush(Colors.Black);
    arcPath.StrokeThickness = 1;
    arcPath.Data = pthGeometry;
    arcPath.Fill = new SolidColorBrush(Colors.Yellow); 

    LayoutRoot.Children.Add(arcPath);
}

 

READ MORE

it's about separating data from layout. So, let's try binding some data to a ListView:

using System;
using System.Collections.Generic;
using System.Windows;

namespace WpfTutorialSamples.ListView_control
{
        public partial class ListViewDataBindingSample : Window
        {
                public ListViewDataBindingSample()
                {
                        InitializeComponent();
                        List<User> items = new List<User>();
                        items.Add(new User() { Name = "John Doe", Age = 42 });
                        items.Add(new User() { Name = "Jane Doe", Age = 39 });
                        items.Add(new User() { Name = "Sammy Doe", Age = 13 });
                        lvDataBinding.ItemsSource = items;
                }
        }

        public class User
        {
                public string Name { get; set; }

                public int Age { get; set; }
        }
}

We populate a list of our own User objects, each user having a name and an age. The data binding process happens automatically as soon as we assign the list to the ItemsSource property of the ListView, but the result is a bit discouraging:

A simple ListView control, using data binding

Each user is represented by their type name in the ListView. This is to be expected, because .NET doesn't have a clue about how you want your data to be displayed, so it just calls the ToString() method on each object and uses that to represent the item.

We can use that to our advantage and override the ToString() method, to get a more meaningful output. Try replacing the User class with this version:

public class User
{
        public string Name { get; set; }

        public int Age { get; set; }

        public override string ToString()
        {
                return this.Name + ", " + this.Age + " years old";
        }
}

A simple ListView control, using data binding and a ToString method on the source object

This is a much more user friendly display and will do just fine in some cases, but relying on a simple string is not that flexible. Perhaps you want a part of the text to be bold or another color? Perhaps you want an image? Fortunately, WPF makes all of this very simple using templates.

ListView with an ItemTemplate

WPF is all about templating, so specifying a data template for the ListView is very easy. In this example, we'll do a bunch of custom formatting in each item, just to show you how flexible this makes the WPF ListView.

Download sample

<Window x:Class="WpfTutorialSamples.ListView_control.ListViewItemTemplateSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ListViewItemTemplateSample" Height="150" Width="350">
    <Grid>
                <ListView Margin="10" Name="lvDataBinding">
                        <ListView.ItemTemplate>
                                <DataTemplate>
                                        <WrapPanel>
                                                <TextBlock Text="Name: " />
                                                <TextBlock Text="{Binding Name}" FontWeight="Bold" />
                                                <TextBlock Text=", " />
                                                <TextBlock Text="Age: " />
                                                <TextBlock Text="{Binding Age}" FontWeight="Bold" />
                                                <TextBlock Text=" (" />
                                                <TextBlock Text="{Binding Mail}" TextDecorations="Underline" Foreground="Blue" Cursor="Hand" />
                                                <TextBlock Text=")" />
                                        </WrapPanel>
                                </DataTemplate>
                        </ListView.ItemTemplate>
                </ListView>
        </Grid>
</Window>

 

READ MORE

While analyzing some controls used for touch devices I found this effective and easy logic for touch control and slow finishing action after touch leaves. Normally in touch devices we like to have control of an application with very smooth touch interaction. We also expect some slow finish of the action, like if we tap and wipe a control then it will move some distance and stay. So I found this logic to do that in an effective manner.

Platform support this approach

  • WPF
  • Windows Stores (WinRT)
  • Windows Phones 8 

Concept behind the approach

In my logic I have handled the manipulation of the data to the control. Using the manipulation of the data, I reset the matrix value of the control as desired. For slow finishing, I used a timer that enables the control for slower and smooth finishing actions after touch leaves.

XAML Code snippet behind the approach

<Button x:Class="TouchApplication.SmoothestTouchControl"

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:DesignHeight="300" d:DesignWidth="300">

  <Grid>

  </Grid>

</Button>

<Window x:Class="TouchApplication.MainWindow"

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

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

Title="MainWindow" Height="350" Width="525"

xmlns:local="clr-namespace:WpfApplication8">

  <Grid >

    <local:SmoothestTouchControl IsManipulationEnabled="True"

    RenderTransform="0.9 0 0 0.9 100 100" />

 

    <local:SmoothestTouchControl IsManipulationEnabled="True"

    RenderTransform="0.9 0 0 0.9 100 100" />

 

    <local:SmoothestTouchControl IsManipulationEnabled="True"

    RenderTransform="0.9 0 0 0.9 100 100" />

 

    <local:SmoothestTouchControl IsManipulationEnabled="True"

    RenderTransform="0.9 0 0 0.9 100 100" />

 

    <local:SmoothestTouchControl IsManipulationEnabled="True"

    RenderTransform="0.9 0 0 0.9 100 100" /

  </Grid>

</Window>

C# code snippet behind the approach
 

// Use required name space  using System;

using System.Linq;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Input;

using System.Windows.Media;

 

namespace TouchApplication

{

    /// Interaction logic for SmoothestTouchControl.xaml

 

    public partial class SmoothestTouchControl : Button

    {

        int i = 0; // Iteration count for slower animation to end

        UIElement uiElement = null; // contains current control

        MatrixTransform matrixTransform = null; // contains Matrix transform

        Matrix uiElementMatrix = new Matrix(); // contains Matrix of the UIElement

        ManipulationDelta manipulationDelta = null; // contains data of Manipulation

        Point centerPoint = new Point(); // contains center point of the element

        System.Windows.Forms.Timer smoother = new System.Windows.Forms.Timer(); // Animater that slow down the action after touch leave

        public SmoothestTouchControl()

        {

            smoother.Interval = 1; // Inverval for animater

            smoother.Tick += smoother_Tick; // hook event to animation

        }

        // override manupulation starting to reset the Z order to get the current touched UI element a top element

        protected override void OnManipulationStarting(ManipulationStartingEventArgs args)

        {

            args.ManipulationContainer = App.Current.MainWindow; // Get the parent window

 

            var frameworkElement = args.Source as FrameworkElement; // Get the current touched element

 

            var panel = frameworkElement.Parent as Panel; // Get parent element to have the children collection

 

            for (int i = 0; i < panel.Children.Count; i++) // Iterate the children collection to reset the Z order

            {

                Panel.SetZIndex(panel.Children[i], panel.Children[i] == frameworkElement ? panel.Children.Count : i);

            }

            args.Handled = true; // Get handled true

 

            base.OnManipulationStarting(args); // Call base for original action

        }

        // override manipulation delta for transform actions

        protected override void OnManipulationDelta(ManipulationDeltaEventArgs args)

        {

            uiElement = args.Source as UIElement; // Get the current touched element

            matrixTransform = uiElement.RenderTransform as MatrixTransform; // Get MatrixTransform of the element

            uiElementMatrix = matrixTransform.Matrix; // Get Matrix of the element

            manipulationDelta = args.DeltaManipulation; // Get delta manipulation of the touch action

            centerPoint = args.ManipulationOrigin; // Get center point of the manipulation

 

            uiElementMatrix.RotateAt(manipulationDelta.Rotation, centerPoint.X, centerPoint.Y); // Rotate the ccontrol acccording to manipulation

            uiElementMatrix.ScaleAt(manipulationDelta.Scale.X, manipulationDelta.Scale.Y, centerPoint.X, centerPoint.Y);// Scale the ccontrol acccording to manipulation

            uiElementMatrix.Translate(manipulationDelta.Translation.X, manipulationDelta.Translation.Y); // Move the ccontrol acccording to manipulation

 

            matrixTransform.Matrix = uiElementMatrix; // Reset the updated matrix to the element matrix

            args.Handled = true; // Get handled true

            base.OnManipulationDelta(args); // Call base for original action

        }

        // override manipulation completed to start slower finish of the touch action

        protected override void OnManipulationCompleted(ManipulationCompletedEventArgs e)

        {

            base.OnManipulationCompleted(e); // Call base for original action

            smoother.Interval = 1; // reset the interval of the slower finish action

            i = 10; // Reset the iterator of the slower finish

            smoother.Start(); // Start animation for slower finish

        }

 

        // slowe finish animater logic

        void smoother_Tick(object sender, EventArgs e)

        {

            i--; // for slow finish action

 

            smoother.Interval = smoother.Interval + 2; // increase interval for integrated slow finish

 

            if (smoother.Interval > 25) // Check for dezire interval

                smoother.Stop(); // Stop the animation

 

            if (manipulationDelta.Rotation != 0) // Check if the control atually in rotation

            {

                uiElementMatrix.RotateAt(manipulationDelta.Rotation - (i > 0 ? i : 1), centerPoint.X, centerPoint.Y); // keep rotation using iterated value

            }

            uiElementMatrix.Translate(manipulationDelta.Translation.X - (i > 0 ? i : 0), manipulationDelta.Translation.Y - (i > 0 ? i : 0)); // keep moving using iterated value

            matrixTransform.Matrix = uiElementMatrix; // reset the updated matrix to the element matrix  

        } 

    }

}

READ MORE
...