top button
Flag Notify
    Connect to us
      Site Registration

Site Registration

Effective and Easy Logic For Touch Control and Slow Finishing Action After Touch Leaves in XAML?

+5 votes
282 views

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  

        } 

    }

}

posted Dec 21, 2015 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
 

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.

 

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

Why XAML is Important

XAML is a modern UI design Markup Language, it helps design a rich UI, 2d and 3d animation, plugin based applications and we also use XAML for:

  • Defining workflow content in Windows Workflow Foundation.
  • Defining services in Windows Communication Foundation.
  • A UI for Silverlight and Windows Presentation Foundation.
  • Rich graphics and animation based application.
  • Arranging controls based on fixed pixel coordinates.

The following summarizes the differences among Windows, Web and XAML Layout applications.

Normal Windows Layout Application

  • Controls have fixed coordinates.
  • The Location property has x and y coordinates representing the upper-left corner of the control retrieve to upper-left corner of container.
  • Some flexibility to dock the ok and cancel buttons to the lower right.
  • Anchor a list box to the left of the form using flow layout to arrange controls in a flow layout.
  • Use table layout to arrange controls in a table format.

Web Form Layout

  • Controls are, by default, anchored relative to the upper-left of the page.
  • You can specify absolute positioning if you want.
  • Re-sizing a window does not change the position of controls.

XAML Layout

  • XAML provides a rich set of built-in layout panels that help you to avoid the common pitfalls.
  • Flow Based Layout.
  • Content is organized in a Container.
  • All Containers are derived from Systems.Window.control.
  • Resolution and Size Independency.
  • Layout automatically adjusts if the screen resolution changes.

Element Size in XAML

  • The size can be specified as an absolute amount of logical units, as a percentage value or automatically.
  • Size is determined by calculating the available screen space, size of constraints and layout-specific properties (Margin, Padding, etc.) behavior of the present Panel.
  • Fixed size of logical units (1/96 inch).
  • Auto takes as much space as needed by the contained control.
  • Star (*) takes as much space as available (after filling all auto and fixed sized columns), proportionally divided over all star-sized columns. So 3*/5* means the same as 30*/50*.

Remember that star-sizing does not work if the grid size is calculated based on its content.

Panels in XAML

  • Grid Panel.
  • Stack Panel.
  • Dock Panel.
  • Wrap Panel.
  • Canvas Panel.

Grid Panel: combination of row and column layout is a Grid Panel; in other words, a Grid Panel arranges controls in a tabular format. The functionality is similar to the HTML table but more flexible as in the following example we try to show a row and column combination for the windows. There are 4 rows and 4 columns.

  • Row and Column definitions in a grid indicate row and column. If you create additional rows and columns, you have to add RowDefinition items to the RowDefinitions collection and ColumnDefinition items to the ColumnDefinitions collection, as the above example shows a grid with 4 rows and 4 columns.

Add controls in Grid Panel

To add controls to the grid layout panel ,just put the declaration between the opening and closing tags of the Grid. Keep in mind that the row and columndefinitions must proceed any definition of child controls.

The grid layout panel provides the two attached properties Grid.Column and Grid.Row to define the location of the control.

In the following example I try to show one normal data entry form design using XAML:



StackPanel

StackPanel is a useful XAML layout. It keeps a control horizontal and vertical; using a stack we design the application like many controls.

Stack Panel common properties are:

  • Stack child element horizontally or vertically.
  • Default is vertical.
  • Use orientation to change to horizontal.
  • Controls positioning of elements by setting their horizontal alignment or vertical alignment properties.
  • Control spacing by setting a margin and padding properties of elements.



Wrap Panel


In a Wrap Panel the child elements are positioned sequentially, from left to right and top to bottom.

By default the layout orientation is horizontal and the controls flow left to right; depending on the screen size the control might wrap to the next line.

By default the screen and code:

    <Grid>
      <Grid.RowDefinitions>
          <RowDefinition></RowDefinition>
      </Grid.RowDefinitions>  
      <Grid.ColumnDefinitions>
            <ColumnDefinition></ColumnDefinition>
        </Grid.ColumnDefinitions>        
        <WrapPanel Grid.Row="0" Grid.Column="0">
            <Button Margin="10">Mango</Button>
            <Button Margin="10">Apple</Button>
            <Button Margin="10">Grape</Button>
            <Button Margin="10">Banana</Button>
            <Button Margin="10">Bilberry</Button>
            <Button Margin="10">Lemon</Button>
        </WrapPanel>
    </Grid>



Elements wrap to the next line once to reduce screen width:



DockPanel: Dock Panel is a most useful layout panel in XAML, it arranges controls to the top, left, bottom, right and remaining space. A useful property is:

  • DockPanel.Dock Property indicates where the element controls are docked.

The default is left; if we don't set the dock property then it will be left:

  • DockPanel.lastChildFill DockPanel will fill up the remaining space of the window.


Canvas Layout:

  • Elements are placed according to coordinates
  • The Canvas layout is similar to Windows forms layout.
  • Elements do not resize automatically at run time.
  • Use canvas.left, canvas.right, canvas.top and canvas.buttom.

Drawbacks:

  • Time consuming and laborious.
  • Harder to line up elements.
  • No resolution and size independence.

Code

    <Canvas>
            <Label Content="Canvas Layout Demo"  FontSize="15" FontWeight="Bold"
                    Foreground="Red"  Canvas.Top="10" Canvas.Left="25"/> 
            <Label Content="ContactInfo" FontSize="12"  Canvas.Top="66" Canvas.Left="10"/> 
            <Label Content="Name"  Canvas.Top="45" Canvas.Left="93"/> 
            <Label Content="Address"  Canvas.Top="90" Canvas.Left="93"/>
            <TextBox  FontSize="15" FontWeight="Bold"         Canvas.Top="45" Canvas.Left="185" Width="93"/>
            <TextBox FontSize="15" FontWeight="Bold"          Canvas.Top="90" Canvas.Left="185" Width="93"/>
   </Canvas>



One small simple Data Entry Form Demo using all panels: stack, dock, wrap, and canvas.

In this example we try to show the real use of these panels and controls in WPF:

 

READ MORE

XAML StatusBar represents a status bar. A StatusBar is a horizontal window that usually sits at the bottom of a window to display various kinds of status information of an application. 

Introduction 

The StatusBar element in XAML represents a WPF StatusBar control. 

  1. <StatusBar></StatusBar>  

The Width and Height properties represent the width and the height of a StatusBar. The Name property represents the name of the control that is a unique identifier of a control. 

The following code snippet creates a StatusBar control and set its content to some text. 

  1. <StatusBar Name="McSBar" Height="30" VerticalAlignment="Bottom"  
  2.            Background="LightBlue" >       
  3.     This is a status bar         
  4. </StatusBar>  

The output looks as in Figure 1. 

status bar
                                                   Figure 1

Creating a StatusBar Dynamically

The StatusBar class in WPF represents a StatusBar control. This class is defined in using the System.Windows.Controls.Primitives namespace. Before you use this class, be sure to import this namespace. 

You may add any number of controls to a StatusBar control. For example, if you add images, a TextBox,TextBlock and/or other controls and place that StatusBar on a Window. The following code snippet creates a StatusBar at run-time and adds a TextBox to it.

  1. private void CreateDynamicStatusBar()  
  2. {  
  3.     StatusBar sBar = new StatusBar();  
  4.     sBar.Height = 30;  
  5.     sBar.Background = new SolidColorBrush(Colors.LightBlue);  
  6.   
  7.     TextBox tb = new TextBox();  
  8.     tb.Text = "This is a status bar";  
  9.     sBar.Items.Add(tb);          
  10.     LayoutRoot.Children.Add(sBar);  
  11. }  
READ MORE

In this article you will learn how to create and use a CustomResource in XAML.

 

  1. Open a new Visual C# windows project.
     
  2. Add a new class named say CustomResourceTest.cs in the project folder.

    CustomResourceTest.cs
     
  3. Derive this class from CustomXamlResourceLoader Class(Case sensitive) like below:

    CustomXamlResourceLoader Class
     
  4. You will get a Namespace not found error. Resolve it by using Windows.UI.Xaml.Resources Namespace.

    Windows.UI.Xaml.Resources
     
  5. Override the GetResource Member of the parent class as below. Use the intellisense to select the member.

    getresource

    getresource1
     
  6. Replace the Code inside the GetResource Method as: (this is just a simple example). We are returning a text. We plan to show this text inside a TextBlock’s Text Property.

    TextBlock
     
  7. Inside the MainPage.cs . Add the following line of code inside the MainPage Constructor to reference the CustomResouceTest.cs Class from the Page’s XAML.

    MainPage

    Correct the NameSpace not found error by resolving it.
     
  8. Now go to the MainPage.xaml Page and Add a TextBlock as follows. Notice the Text property of the TextBlock.

    MainPage.xaml
     
  9. This results in the following output when you save, build and run the project.

    run
     
  10. What is happening here?
     
    • We created a CustomResourceClass where we inherited the Class called CustomXamlResourceLoader.
    • We override the GetResourceProperty. Don’t focus on the parameters of this method for now.
    • We replaced the code inside this method by simply returning a text.
    • To access this CustomResource from XAML we have to define the CustomXamlResourceLoader. Current property to the new instance of the Class we created. We have to do this inside the Constructor of the Codebehind page where we want to use the CustomResource.
    • We then simply assigned the value of the Text property of the textblock to the CustomResource as seen on Step 8.

Example 2:

  1. Now we will try a different example where we want to display the Text of the TextBlock based on the value we pass on. Change the text of the Mainpage.xaml as:

    Mainpage.xaml 2
     
  2. The 'sayHello' string is passed as a string to the CusomResourceTest.cs class as ResourceID parameter of the overridden class. This will be more clear as you see in the next step.
     
  3. In the CustomResourceTest.cs class , change the code as follows:

    CustomResourceTest.cs2
     
  4. The thing to understand is how we pass the ResourceID from the Text Property of the TextBlock. It is passed as the resourceID parameter. So, based on the ResourceID, we return the appropriate text we want to display on the output screen.
     
  5. So now we get output as.
  6. If we change the text property as sayByeBye.

    sayByeBye
     
  7. We get the following output:
     
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
...