tag:blogger.com,1999:blog-78413695541223518962024-02-19T00:19:31.631-08:00My Technical Blogs for WPF / Windows Phone 7/ SilverlightNishant Ranahttp://www.blogger.com/profile/04447027857465485472noreply@blogger.comBlogger8125tag:blogger.com,1999:blog-7841369554122351896.post-39958561520374527792014-02-02T10:57:00.000-08:002014-03-30T04:26:01.578-07:00Pattern Lock for Windows Phone<div dir="ltr" style="text-align: left;" trbidi="on">
Do you have a <i><b>security</b></i> / <i><b>privacy</b></i> application? You need to lock your application's screen to provide secure access? Well, I am writing a series of open source control which will help you do just that!<br />
<br />
In this first article, I am going to cover how to create a Pattern Lock or Swipe Lock, that you might have seen quite often on Android platform. This is my second effort to port such functionality from Android platform or other platforms. First up is <a href="http://nishantcop.blogspot.in/2012/12/notification-notch-control-for-windows.html" target="_blank">Notification Notch Control</a>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgaqjcQSbmKtExEq5YkDMM5G6CmvG9RqxTvEjFiF4yQyiiEmc0wD23BkX0u-Z36DDsqZMkrM5tuq7JqNhJUQcWITJlIe0WGnG805Rg41r-ea_X8MnuRMQP2czsrDXaaYrg2KIk6dFMt9emk/s1600/Android+Pattern+Lock.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgaqjcQSbmKtExEq5YkDMM5G6CmvG9RqxTvEjFiF4yQyiiEmc0wD23BkX0u-Z36DDsqZMkrM5tuq7JqNhJUQcWITJlIe0WGnG805Rg41r-ea_X8MnuRMQP2czsrDXaaYrg2KIk6dFMt9emk/s1600/Android+Pattern+Lock.JPG" /></a></div>
<b>Image 1</b>. <i>A sample for swipe lock</i><br />
<br />
Well, I'll try to create something which blends nicely with Modern UI a.k.a Metro.<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnwFrqBJG06QRYLJE1SxPxoL3Ke7v1LvQuhOGvGogEI2AMvKM35OXOlKLPdzJmCGi4mKK6gecBQIevd-PfrNwGP6xETW__syMtLsmgfwmkDpzHbVZOAf37D0jjqdCjT7KzN7v8U5B_-MMx/s1600/WPPatternLock_Blue.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnwFrqBJG06QRYLJE1SxPxoL3Ke7v1LvQuhOGvGogEI2AMvKM35OXOlKLPdzJmCGi4mKK6gecBQIevd-PfrNwGP6xETW__syMtLsmgfwmkDpzHbVZOAf37D0jjqdCjT7KzN7v8U5B_-MMx/s1600/WPPatternLock_Blue.PNG" /></a></div>
<b>Image 2</b>. <i>A sample for WP swipe lock</i><br />
<br />
<h4>
PREREQUISITE: </h4>
<div>
<br /></div>
<div>
1. Knowledge of <a href="http://msdn.microsoft.com/en-us/magazine/dd419663.aspx" rel="nofollow" target="_blank">MVVM</a> in .Net.<br />
2. <a href="http://mvvmlight.codeplex.com/" rel="nofollow" target="_blank">MVVM Light Toolkit</a>.<br />
<br />
<h4>
</h4>
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlb_0k2TCwVSVa1Gus4ULr6vIrmhgTEnrnjK2PBoLQyBoN06tMvmRJchujrTA6zbrNEmwLgb7u325_lkHfzO5DyDRUkE8WLVgJLYUZjZNF3Gzidp6VWWCJy15ThgqcDWnsg5W456XgRp2x/s1600/ProjectSnapshot.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlb_0k2TCwVSVa1Gus4ULr6vIrmhgTEnrnjK2PBoLQyBoN06tMvmRJchujrTA6zbrNEmwLgb7u325_lkHfzO5DyDRUkE8WLVgJLYUZjZNF3Gzidp6VWWCJy15ThgqcDWnsg5W456XgRp2x/s1600/ProjectSnapshot.PNG" /></a></div>
<div>
<b>Image 3</b>. <i>Snapshot for Project's core component</i></div>
<h4 style="text-align: left;">
<u><br />
</u></h4>
<h4 style="text-align: left;">
<u>LETS START BUILDING THE CONTROL:</u> </h4>
We will quickly watch for the core STEPS to build this control.<br />
<br />
<h4>
CREATE RECTANGULAR COMPONENT:</h4>
<div>
Our main component is <i><b>Rectangle</b></i> (which fits well in Metro design) as shown in image 2.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcJrgTzNkRRvA8CCpkjFqM1JB2Hz6JNZ5sX1ph19j5cZP3qaZ_C21i_1bRI4R2EeVm6MUV1qyfQ_tBFES7d2PvLMaJpcWxZeuuXVE9RoS4ZpHrYQAv6ApduSlfcTgUAQyfQIHkfxUzbOiE/s1600/PatternBoxUnSelected.PNG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"> <img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcJrgTzNkRRvA8CCpkjFqM1JB2Hz6JNZ5sX1ph19j5cZP3qaZ_C21i_1bRI4R2EeVm6MUV1qyfQ_tBFES7d2PvLMaJpcWxZeuuXVE9RoS4ZpHrYQAv6ApduSlfcTgUAQyfQIHkfxUzbOiE/s1600/PatternBoxUnSelected.PNG" /> </a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9U7PTjuTMm30Tm9RI0bpIb4pLeGV7w-WbvjHuXks5QDS10bXDLDtSiHfZLxWxtQUAIdAAWTez30NvEWlay0cI7vtyvbM8Nrzzro4gRJ5NXrMgvNHMNTzmOd7PVtYHF4JhhSumyZQCjSER/s1600/PatternBoxSelected.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9U7PTjuTMm30Tm9RI0bpIb4pLeGV7w-WbvjHuXks5QDS10bXDLDtSiHfZLxWxtQUAIdAAWTez30NvEWlay0cI7vtyvbM8Nrzzro4gRJ5NXrMgvNHMNTzmOd7PVtYHF4JhhSumyZQCjSER/s1600/PatternBoxSelected.PNG" /></a> </div>
<br />
<b>Image 4</b>. <i>Rectangle when not selected </i><b>Image 5</b>. <i>Rectangle when selected</i><i> </i><br />
<br />
Following code is used to build square component:<br />
<br />
<pre class="brush:csharp" lang="csharp">using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Media;
using System.Windows;
using System.Windows.Controls;
namespace PatternLockControl.Code
{
public class SquarePattern : PatternDesignBase
{
#region Data
#region SquareProperty
private Border _Square;
public Border Square
{
get
{ return _Square; }
set
{
if (_Square == value)
{
return;
}
_Square = value;
RaisePropertyChanged("Square");
}
}
#endregion
/// <summary>
/// Sets or gets the Zindex Value for Icon
/// </summary>
public override int ZIndexVal
{
get { return (int)Square.GetValue(Canvas.ZIndexProperty); }
set { Square.SetValue(Canvas.ZIndexProperty, value); }
}
#region BorderColProperty
private Color _BorderCol;
public Color BorderCol
{
get
{ return _BorderCol; }
set
{
if (_BorderCol == value)
{
return;
}
_BorderCol = value;
RaisePropertyChanged("BorderCol");
BorderBrush = new SolidColorBrush(_BorderCol);
}
}
#endregion
#region BorderBrushProperty
private SolidColorBrush _BorderBrush;
public SolidColorBrush BorderBrush
{
get
{ return _BorderBrush; }
private set
{
if (_BorderBrush == value)
{
return;
}
_BorderBrush = value;
RaisePropertyChanged("BorderBrush");
}
}
#endregion
public int Row { get; set; }
public int Column { get; set; }
#endregion
#region Constructor
public SquarePattern(int row, int column, int width, int value, Color fillNormal, Color fillSelected, Color borderCol)
: base(fillNormal, fillSelected, value)
{
this.FillColNormal = fillNormal;
this.BorderCol = borderCol;
this.Row = row;
this.Column = column;
Square = new Border() { Name = string.Concat(row, column), Width = width, Height = width, Background = this.FillBrushNormal, BorderBrush = BorderBrush, BorderThickness = new Thickness(2) };
ZIndexVal = 1;
}
#endregion
#region Methods
public override void GridPosition(int row, int col)
{
Square.SetValue(Grid.RowProperty, row);
Square.SetValue(Grid.ColumnProperty, col);
}
public override void MarkAsSelected()
{
this.Square.Background = FillBrushSelected;
}
#endregion
}
}</pre>
<br />
Note: This <i>class</i> inherits from <i>PatternDesignBase</i> (abstract) class. <i>PatternDesignBase</i> work as a base class for such controls which could have different core items like Square (in current sample), Triangle, Circles, etc.<br />
<div>
<br />
<h4>
CREATE LAYOUT ROOT :</h4>
<div>
This control's layout will be hosted in a <i><a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.usercontrol(v=vs.110).aspx" target="_blank">UserControl</a></i> which also implements it's <i>core functionality</i> for Pattern Lock Control.<br />
<br />
Full code can be found in <i>PatternLockMetroControl.cs</i> and <i>PatternLockMetroControl.xaml.</i> I am going to list down important functionalities from it. <br />
<div>
<ol style="text-align: left;">
<li><b>InitializeAnimateGrid.</b> </li>
<li><b>DrawLine</b>.</li>
<li><b>AddPolygon</b>: . </li>
</ol>
</div>
</div>
<b>InitializeAnimateGrid</b><br />
This method is responsible to initializing <i>SquarePatterns</i> and placing them into a <a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.grid(v=vs.110).aspx" target="_blank">Grid</a> control which collectively forms core of this control<br />
<br />
<pre class="brush:csharp" lang="csharp">private void InitializeAnimateGrid()
{
LockPatterShapes = new ObservableCollection<squarepattern>();
var chromeColor = (this.Resources["PhoneAccentBrush"] as SolidColorBrush).Color;
int pattVal = 0;
for (int row = 0, maxRows = RootContainer.RowDefinitions.Count; row < maxRows; ++row)
{
for (int col = 0, maxCols = RootContainer.ColumnDefinitions.Count; col < maxCols; ++col)
{
var LockPatterShape = new SquarePattern(row, col, 100, pattVal++, Colors.Black, chromeColor, chromeColor);
LockPatterShape.GridPosition(row, col);
RootContainer.Children.Add(LockPatterShape.Square);
LockPatterShape.Square.MouseEnter += SquarePattern_MouseMoveEvent;
LockPatterShape.Square.MouseLeftButtonUp += Square_MouseLeftButtonUp;
LockPatterShapes.Add(LockPatterShape);
}
}
}</squarepattern></pre>
</div>
<br />
<b>DrawLine</b><br />
This methods holds the responsibility to draw lines between two square pattern, as we continue to swipe. There are certain methods available in LineHelper class which helps to complete the task by this method. This method comes into action when user starts moving his fingers on screen. I've captured the sample code for a quick reference here.<br />
<br />
<pre class="brush:csharp" lang="csharp">private void DrawLine()
{
if (MyPattern.Count < 2) return;
if (_MouseMoveLine != null)
{
RootContainer.Children.Remove(_MouseMoveLine);
_MouseMoveLine = null;
}
Point ptDest, ptSource;
var sqPattEnd = MyPattern.LastOrDefault().Value;
var sqPattStart = MyPattern.ElementAt(MyPattern.Count - 2).Value;
//Find points to draw line from start and end.
ptDest = LineHelper.GetPtRelativeToQuadrant(RootContainer, sqPattEnd.Square, LineHelper.FindQuadrantToDrawLineBW(sqPattEnd.Row, sqPattEnd.Column, sqPattStart.Row, sqPattStart.Column));
ptSource = LineHelper.GetPtRelativeToQuadrant(RootContainer, sqPattStart.Square, LineHelper.FindQuadrantToDrawLineBW(sqPattStart.Row, sqPattStart.Column, sqPattEnd.Row, sqPattEnd.Column));
Line line;
LineType lType = LineHelper.FindLineType(sqPattStart.Row, sqPattStart.Column, sqPattEnd.Row, sqPattEnd.Column);
if (lType == LineType.SIMPLE)
line = LineHelper.CreateLine(ptSource, ptDest, DragLineWidth, (this.Resources["PhoneAccentBrush"] as SolidColorBrush), ZIdxForDrawnLines++, RootContainer, lType);
else
line = LineHelper.CreateLine(ptSource, ptDest, DottedLineWidth, SelectedLineBrush, ZIdxForDrawnLines++, RootContainer, lType);
AddPolygon(MyPattern.ElementAt(MyPattern.Count - 2).Value.Square, LineHelper.FindQuadrantToDrawLineBW(sqPattStart.Row, sqPattStart.Column, sqPattEnd.Row, sqPattEnd.Column));
RootContainer.Children.Add(line);
}</pre>
<br />
<br />
<br />
<b>AddPolygon</b><br />
This method generates tiny white colored triangle. These little triangles indicate the direction of swipe when user swipes it's fingers from one rectangle to another. These triangles will only be visible when they have moved from one rectangle to another. Logic to identify where the triangles to be drawn is written inside GetPoinstForPolygon(). A sample code for AddPolygon is referenced here: <br />
<br />
<pre class="brush:csharp" lang="csharp">private void AddPolygon(Border shape, LineQuadrant quad)
{
Polygon poly = new Polygon();
poly.Fill = new SolidColorBrush(Colors.White);
poly.Points = LineHelper.GetPointsForPolygon(shape.ActualWidth, quad, poly);
shape.BorderThickness = new Thickness(0);
shape.Child = poly;
//Set the Max ZIdx for poly/Border so that it will always be on top of all drawn lines
shape.SetValue(Canvas.ZIndexProperty, ZIdxForDrawnLines + 1);
}</pre>
<br />
That's it!! We are DONE!!!<br />
<br />
<br />
<h4>
OTHER IMPORTANT FEATURES / INFO:</h4>
<div>
1. <b>Registration Mode :</b> We can easily configure this control to register a new pattern or to use verify an existing pattern</div>
<div>
2. <b>Decoy Pattern :</b> This feature provides an additional flexibility to register additional set of pattern. This will be helpful in case you want your application to support multiple access mode say one for <b>Admin </b>and another for <b>User </b>mode. </div>
3. <b>Pattern Format :</b> Based on your selection i.e. <i>Registration Mode</i> or <i>Verify Pattern</i> mode this control will generate an event to publish the result. In case of <i>Registration</i> mode if your selection is as per Image 6 then it will return a List of integer [1,2,3,6,9].<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjt03O8GLJQ5rnVWDa9R8BNAD7JLiDppzxoRYwa7tlviFot1f8fwmfb14C0AkhqP5JDvekYLyXBPQyxFYQwk0F7NiU4CsW7Apa3ohV0dHJ-1xFyrMqS5mrx05RYZG3aIDQYx1MD4hwq0oFI/s1600/LockMappingToNumbers.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjt03O8GLJQ5rnVWDa9R8BNAD7JLiDppzxoRYwa7tlviFot1f8fwmfb14C0AkhqP5JDvekYLyXBPQyxFYQwk0F7NiU4CsW7Apa3ohV0dHJ-1xFyrMqS5mrx05RYZG3aIDQYx1MD4hwq0oFI/s1600/LockMappingToNumbers.png" height="310" width="320" /></a></div>
<b>Image 6</b>. <i>A sample selection for result.</i><br />
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div>
<h2>
VIDEO</h2>
</div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/pk-XiQj5XBc?feature=player_embedded' frameborder='0'></iframe></div>
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div>
</div>
<div>
</div>
<div>
<a href="https://wppatternlock.codeplex.com/SourceControl/latest" target="_blank">Latest Source Code</a></div>
</div>
Nishant Ranahttp://www.blogger.com/profile/04447027857465485472noreply@blogger.com0tag:blogger.com,1999:blog-7841369554122351896.post-1887761596107466112012-12-24T20:03:00.003-08:002014-01-26T06:20:31.677-08:00Notification Notch Control for Windows Phone<div dir="ltr" style="text-align: left;" trbidi="on">
Many of you would have wondered why there is no <i>Notification Notch</i> in <a class="g-profile" href="https://plus.google.com/communities/110562600644280241239" target="_blank">+Windows Phone</a>, similar to the one seen first in Android and then later in iOS5 as well. However, there might be some restriction/limitation for them (WP team) to implement <i>Notification Notch</i> at this point of time but this shouldn't stop you from implementing it in your application. In today's article I am going to explain how to create a Notification Notch and how to use it in your application.<br />
<br />
Well, our objective will be completed in 3 steps:<br />
<br />
1. Create a custom <a href="http://msdn.microsoft.com/en-us/library/system.windows.forms.design.behavior.behavior.aspx" target="_blank">behavior</a> i.e. "<b style="font-style: italic;">Drag Notch Behavior</b>" to mimic drag and expand/close nature of a notification notch.<br />
2. Create a sample user control i.e. "<b><i>Drag Notch Control</i></b>" to use this behavior.<br />
3. Create a sample project to use this control. <br />
<br />
<h4 style="text-align: left;">
PREREQUISITE: </h4>
<div>
1. Knowledge of <a href="http://msdn.microsoft.com/en-us/library/system.windows.forms.design.behavior.behavior.aspx" target="_blank">Behavior</a> in .Net<br />
<br /></div>
<h4 style="text-align: left;">
BUILDING HELPER CLASSES:</h4>
<div>
There are a few extension methods that are required to easily find and manipulate a <i>FrameworkElemant</i> from code. For doing so I've shamelessly pinched the code from "Joost van Schaik" code article - "<a href="http://dotnetbyexample.blogspot.sg/2011/03/simple-windows-phone-7-silverlight.html" target="_blank">Simple Windows Phone 7 / Silverlight drag/flick behavior</a>". These Libraries can be found under utilities in my sample code attached.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYRY5I-j5u-tz39LLXCFbn4jmbRD047bQ8fETc5bYDITsf_0bbL4UMtwVQ10ymp-VDIWpqPUMEofAWTsPLoLA509TuV-bqUC0dxKb4e1Ofwq7Y_xIyr5A9LzPvEdwtZnmT3w8Uce0BoiHd/s1600/Utilities.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img alt="" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYRY5I-j5u-tz39LLXCFbn4jmbRD047bQ8fETc5bYDITsf_0bbL4UMtwVQ10ymp-VDIWpqPUMEofAWTsPLoLA509TuV-bqUC0dxKb4e1Ofwq7Y_xIyr5A9LzPvEdwtZnmT3w8Uce0BoiHd/s1600/Utilities.jpg" title="Helper Classes" /></a></div>
<div>
<br /></div>
<h4 style="text-align: left;">
<br />
</h4>
<h4 style="text-align: left;">
<br />
</h4>
<h4 style="text-align: left;">
<br />
</h4>
<h4 style="text-align: left;">
<br />
</h4>
<h4 style="text-align: left;">
<br />
</h4>
<h4 style="text-align: left;">
<br />
</h4>
<h4 style="text-align: left;">
</h4>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<h4 style="text-align: left;">
DRAG NOTCH BEHAVIOR:</h4>
<div>
Code for DragNotch Behavior is implemented by following class:</div>
<div>
<pre class="brush:csharp" lang="csharp">using System;
using System.Windows;
using System.Windows.Input;
using System.Windows.Interactivity;
using System.Windows.Media;
using System.Windows.Media.Animation;
using nishantcop_Behaviors.Utilities;
namespace nishantcop_Behaviors.Behaviors
{
public class DragNotchBehavior : Behavior<frameworkelement>
{
private FrameworkElement _elementToAnimate;
public event NotchStateChangedHandler NotchStateChanged;
public delegate void NotchStateChangedHandler(object sender, NotchStateChangedEventArgs e);
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.Loaded += AssociatedObjectLoaded;
AssociatedObject.ManipulationDelta += AssociatedObjectManipulationDelta;
AssociatedObject.ManipulationCompleted += AssociatedObjectManipulationCompleted;
}
void AssociatedObjectLoaded(object sender, RoutedEventArgs e)
{
_elementToAnimate = AssociatedObject.GetElementToAnimate();
if (!(_elementToAnimate.RenderTransform is CompositeTransform))
{
_elementToAnimate.RenderTransform = new CompositeTransform();
_elementToAnimate.RenderTransformOrigin = new Point(0.5, 0.5);
}
StartPosition = AssociatedObject.GetTranslatePoint();
}
void AssociatedObjectManipulationDelta(object sender, ManipulationDeltaEventArgs e)
{
//var dx = e.DeltaManipulation.Translation.X;
var dy = e.DeltaManipulation.Translation.Y;
var currentPosition = _elementToAnimate.GetTranslatePoint();
_elementToAnimate.SetTranslatePoint(currentPosition.X, currentPosition.Y + dy);
}
private void AssociatedObjectManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
{
// Create a storyboard that will emulate a 'flick'
var currentPosition = _elementToAnimate.GetTranslatePoint();
var velocity = e.FinalVelocities.LinearVelocity;
if (velocity.Y > 0)
{
//var to = new Point(currentPosition.X, 360 + (velocity.Y / BrakeSpeed));
}
var storyboard = new Storyboard { FillBehavior = FillBehavior.HoldEnd };
var to = new Point(currentPosition.X + (velocity.X / BrakeSpeed),
currentPosition.Y + (velocity.Y / BrakeSpeed));
storyboard.AddTranslationAnimation(_elementToAnimate, currentPosition, GetEndPoint(),
new Duration(TimeSpan.FromMilliseconds(500)),
new CubicEase { EasingMode = EasingMode.EaseOut });
storyboard.Begin();
}
protected override void OnDetaching()
{
AssociatedObject.Loaded -= AssociatedObjectLoaded;
AssociatedObject.ManipulationCompleted -= AssociatedObjectManipulationCompleted;
AssociatedObject.ManipulationDelta -= AssociatedObjectManipulationDelta;
base.OnDetaching();
}
private Point GetEndPoint()
{
double midPoint = Math.Abs(StartPosition.Y) - Math.Abs(_elementToAnimate.GetTranslatePoint().Y);
if (midPoint &lt; Math.Abs(StartPosition.Y) / 2)
{
NotchStateChanged(this, new NotchStateChangedEventArgs(false));
return StartPosition;
}
else
{
IsNotchExpanded = true;
NotchStateChanged(this, new NotchStateChangedEventArgs(true));
return EndPosition;
}
}
/// <summary>
/// This function tries to collapse a notch if it's expanded.
/// </summary>
public void TryRollBackNotch()
{
var currentPosition = _elementToAnimate.GetTranslatePoint();
if (currentPosition != StartPosition)
{
var storyboard = new Storyboard { FillBehavior = FillBehavior.HoldEnd };
storyboard.AddTranslationAnimation(_elementToAnimate, currentPosition, StartPosition,
new Duration(TimeSpan.FromMilliseconds(500)),
new CubicEase { EasingMode = EasingMode.EaseOut });
storyboard.Begin();
storyboard.Completed += new EventHandler(storyboard_Completed);
}
}
void storyboard_Completed(object sender, EventArgs e)
{
var storyboard = sender as Storyboard;
storyboard.Completed -= storyboard_Completed;
IsNotchExpanded = false;
NotchStateChanged(this, new NotchStateChangedEventArgs(false));
}
#region IsNotchExpandedProperty
public bool IsNotchExpanded
{
get { return (bool)GetValue(IsNotchExpandedProperty); }
set { SetValue(IsNotchExpandedProperty, value); }
}
// Using a DependencyProperty as the backing store for IsNotchExpanded. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsNotchExpandedProperty =
DependencyProperty.Register("IsNotchExpanded", typeof(bool), typeof(DragNotchBehavior), new PropertyMetadata(false, OnIsNotchExpandedPropertyChanged));
private static void OnIsNotchExpandedPropertyChanged(DependencyObject source,
DependencyPropertyChangedEventArgs e)
{
DragNotchBehavior behavior = source as DragNotchBehavior;
bool time = (bool)e.NewValue;
// Put some update logic here...
}
#endregion
#region BrakeSpeed
public const string BrakeSpeedPropertyName = "BrakeSpeed";
/// <summary>
/// Describes how fast the element should brake, i.e. come to rest,
/// after a flick. Higher = apply more brake ;-)
/// </summary>
public int BrakeSpeed
{
get { return (int)GetValue(BrakeSpeedProperty); }
set { SetValue(BrakeSpeedProperty, value); }
}
public static readonly DependencyProperty BrakeSpeedProperty = DependencyProperty.Register(
BrakeSpeedPropertyName,
typeof(int),
typeof(DragNotchBehavior),
new PropertyMetadata(10));
#endregion
#region StartPosition
public Point StartPosition
{
get { return (Point)GetValue(StartPositionProperty); }
set { SetValue(StartPositionProperty, value); }
}
// Using a DependencyProperty as the backing store for StartPosition. This enables animation, styling, binding, etc...
public static readonly DependencyProperty StartPositionProperty =
DependencyProperty.Register("StartPosition", typeof(Point), typeof(DragNotchBehavior), new PropertyMetadata(new Point(0, 0)));
#endregion
#region End Position
public Point EndPosition
{
get { return (Point)GetValue(EndPositionProperty); }
set { SetValue(EndPositionProperty, value); }
}
// Using a DependencyProperty as the backing store for EndPosition. This enables animation, styling, binding, etc...
public static readonly DependencyProperty EndPositionProperty =
DependencyProperty.Register("EndPosition", typeof(Point), typeof(DragNotchBehavior), new PropertyMetadata(new Point(0, 0)));
#endregion
}
}</frameworkelement></pre>
</div>
<div>
<br /></div>
<div>
This behavior exposes following important properties:</div>
<div>
<ol style="text-align: left;">
<li><b>StartPosition</b>: Element starts it's animation at this point. </li>
<li><b>EndPostion</b>: Element ends it's animation at this point.</li>
<li><b>BrakeSpeed</b>: Speed by which animation should come to halt. </li>
<li><b>TryRollBackNotch</b>: A Function to force close/Rollback your <i>Notification Notch</i> control. </li>
<li><b>NotchStateChanged</b>: An <a href="http://msdn.microsoft.com/en-us/library/aa645739(v=vs.71).aspx" target="_blank">Event</a> to notify the change in status of <i>Notification Notch</i> control i.e. closed or expanded. </li>
</ol>
</div>
<div>
If you wish to fiddle around with it you can change the behavior to move <i>horizontally </i>only, contrasted to it's default <i>vertical </i>movement.</div>
<div>
<br /></div>
<div>
For adding a NotchStateChanged <a href="http://msdn.microsoft.com/en-us/library/aa645739(v=vs.71).aspx" target="_blank">Event</a> you will need to provide an customized <a href="http://msdn.microsoft.com/en-us/library/system.eventargs(v=vs.95).aspx" target="_blank">EventArgs</a> class. Code for which will look like this: </div>
<div>
<pre class="brush:csharp" lang="csharp">using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace nishantcop_Behaviors.Utilities
{
public class NotchStateChangedEventArgs : EventArgs
{
private bool _IsNotchExpanded;
public NotchStateChangedEventArgs(bool isNotchExpanded)
{
this._IsNotchExpanded = isNotchExpanded;
//this.exceededPercentage = exceededPercentage;
// not shown - validation for input
}
public bool IsNotchExpanded
{
get { return this._IsNotchExpanded; }
}
}
}
</pre>
</div>
<div>
<br /></div>
<div>
This class provides current state for your <i>Notch Control</i>. We handle this class in our Drag Notch Behavior whenever we are animating our control for expanding and closing it. </div>
<div>
<br /></div>
<div>
So, that's about the Drag Notch Behavior now lets take a look into how exactly to use it in your project. </div>
<div>
<br /></div>
<h2>
DRAG NOTCH CONTROL</h2>
<div>
<div style="text-align: left;">
Now we need a DragNotch control that can be used across our application. A sample xaml for DragNotch control is: </div>
<div style="text-align: left;">
</div>
<pre class="brush:xml" lang="csharp"><usercontrol d:designheight="607" d:designwidth="456" mc:ignorable="d" x:class="WPTestBehavior.DragNotch" xmlns:custombehaviors="clr-namespace:nishantcop_Behaviors.Behaviors;assembly=nishantcop_Behaviors" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<grid background="#FF0060AB" rendertransformorigin="0.5,0.5" x:fieldmodifier="public" x:name="grd">
<i:interaction .behaviors=".behaviors">
<custombehaviors:dragnotchbehavior notchstatechanged="Notch_NotchStateChanged" x:fieldmodifier="public" x:name="Notch">
</custombehaviors:dragnotchbehavior></i:interaction>
<grid .rendertransform=".rendertransform">
<compositetransform translatey="-658">
</compositetransform></grid>
<img d:layoutoverrides="Height" height="48" margin="0,0,0,-17" source="/images/NotificationNotch.png" verticalalignment="Bottom" width="48" />
<listbox horizontalalignment="Left" verticalalignment="Top" x:name="lbx">
</listbox></grid>
</usercontrol></pre>
</div>
<div>
This control simply contains a Grid and our DragNotchBehavior is attached to it. For this custom behavior we need to set it's x:fieldModifier = "public" so that we can access it from code behind. Also we need to set the TranslateY property of CompositeTransform to a suitable position so that it won't be visible until it's being dragged. For this demo I've set this value to -700. However it can be easily tweaked as per your requirement.<br />
<br />
Code behind for your DragNotch control:<br />
<br />
<pre class="brush:csharp" lang="csharp">using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace WPTestBehavior
{
public partial class DragNotch : UserControl
{
public DragNotch()
{
// Required to initialize variables
InitializeComponent();
}
private void Notch_NotchStateChanged(object sender, nishantcop_Behaviors.Utilities.NotchStateChangedEventArgs e)
{
bool b = e.IsNotchExpanded;
}
public void RollBackNotch()
{
Notch.TryRollBackNotch();
}
}
}</pre>
<br />
In code behind we are handling the NotchStateChanged event from our behavior and a public method (RollBackNotch) is exposed so that you can force your control to collapsed.<br />
<br />
Now, your control is ready you can fill in whatever you want inside this grid, for your notification purpose or whatever you may want to call it :-)<br />
<br />
<h2 style="text-align: left;">
USE DRAG NOTCH CONTROL</h2>
For using the DragNotch control in last step I've created this sample page:<br />
<br />
<pre class="brush:xml" lang="csharp"><phone:phoneapplicationpage d:designheight="768" d:designwidth="480" fontfamily="{StaticResource PhoneFontFamilyNormal}" fontsize="{StaticResource PhoneFontSizeNormal}" foreground="{StaticResource PhoneForegroundBrush}" mc:ignorable="d" orientation="Portrait" shell:systemtray.isvisible="True" supportedorientations="Portrait" x:class="WPTestBehavior.MainPage" xmlns:custom="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:WPTestBehavior" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:nishantcop_behaviors="clr-namespace:nishantcop_Behaviors.Behaviors;assembly=nishantcop_Behaviors" xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone" xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<!--LayoutRoot is the root grid where all page content is placed-->
<grid background="Transparent" x:name="LayoutRoot">
<grid .rowdefinitions=".rowdefinitions">
<rowdefinition height="Auto">
<rowdefinition height="*">
</rowdefinition></rowdefinition></grid>
<!--TitlePanel contains the name of the application and page title-->
<stackpanel grid.row="0" margin="12,17,0,28" x:name="TitlePanel">
<!--ContentPanel - place additional content here-->
<grid grid.row="1" margin="12,0,12,0" x:name="ContentPanel">
<listbox x:name="lbx">
<local:dragnotch x:name="TestDragNotch">
<img doubletap="Image_DoubleTap" source="/images/titlebar.png" verticalalignment="Top" />
</local:dragnotch></listbox></grid>
</stackpanel></grid>
</phone:phoneapplicationpage></pre>
</div>
<div>
This page contains ListBox filled with some sample data and our "TestDragNotch" control to overlay it when it's expanded to demonstrate the <i>Notification Notch</i> behavior.<br />
<br />
<h2 style="text-align: left;">
VIDEO</h2>
</div>
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/CmD0i3ex1ME?feature=player_embedded' frameborder='0'></iframe></div>
<div>
</div>
<div>
</div>
<div>
<a href="https://skydrive.live.com/#cid=CB9B95B4DD4D63A6&id=CB9B95B4DD4D63A6%211009" target="_blank">Source Code</a></div>
</div>
Nishant Ranahttp://www.blogger.com/profile/04447027857465485472noreply@blogger.com2tag:blogger.com,1999:blog-7841369554122351896.post-80457852095996619902012-12-02T08:19:00.001-08:002013-05-02T23:32:21.157-07:00Mashape API - How to Consume in WP<div dir="ltr" style="text-align: left;" trbidi="on">
Today I'll talk about <a href="https://www.mashape.com/" target="_blank">Mashape</a> APIs and their integration into WP project. Before getting into more details I'll like to answer few FAQs.<br />
<br />
<b>Q1 </b>: What is Mashape?<br />
<b>Ans</b>: Mashape is API cloud based API hub. You can used hosted API there and can quickly develop an application.<br />
<br />
<b>Q2 </b>: How can I use that in WP Application?<br />
<b>Ans</b>: You can consume their API(s) using REST services in WP. (Soon, auto generated client libraries will also be supported for WP code).<br />
<br />
<h2 style="text-align: left;">
Prerequisite:</h2>
1. <a href="http://json.codeplex.com/" target="_blank">Json Client Library</a>: This library will be helpful to consume Json response from Mashape's AP. Download the source code and compile it for the WP version you are going to use and then add in your project and use. <br />
<br />
<h2 style="text-align: left;">
How to consume REST API in Windows Phone</h2>
For my sample app I am consuming <a href="https://www.mashape.com/mutationevent/qr-code-generator" target="_blank">QR code generator</a> API.<br />
<br />
1. <b>Create a WebClient Request</b>:<br />
<br />
<pre class="brush:csharp" lang="csharp">WebClient client = new WebClient();</pre>
<br />
2. <b>Set Content Type in request's Header</b>:<br />
<br />
<pre class="brush:csharp" lang="csharp">client.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";</pre>
<br />
<br />
3. <b>Add Authorization Header</b>: An authorization code is required to authenticate each request, this code can be easily generated by a tool provided at <a href="https://www.mashape.com/docs/consume/rest" target="_blank">this link</a> for all registered Mashape users<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZKfHiQ5fX3LWT_A7AN9RvWhSqhEASGN4OK5YhKd_HdceFHMNDpNfPvK-sXVN0k0WDVkwocbHEbrBZIqYv0uo1TDTOkR5Zy5WfHT3LOW9Lz5KSQX_u-0gm-9YNBoMbiu1VxNyHzBe4ibYQ/s1600/AuthHeaderTool.JPG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="78" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZKfHiQ5fX3LWT_A7AN9RvWhSqhEASGN4OK5YhKd_HdceFHMNDpNfPvK-sXVN0k0WDVkwocbHEbrBZIqYv0uo1TDTOkR5Zy5WfHT3LOW9Lz5KSQX_u-0gm-9YNBoMbiu1VxNyHzBe4ibYQ/s640/AuthHeaderTool.JPG" width="640" /></a></div>
<br />
<br />
<br />
<br />
<br />
<pre class="brush:csharp" lang="csharp">client.Headers["X-Mashape-Authorization"] = "YourAutorizationHeaderNeedToGenerateFromTool";</pre>
<br />
<br />
4. <b>Add Data for Web Request</b>:<br />
<br />
<pre class="brush:csharp" lang="csharp">StringBuilder postData = new StringBuilder();
postData.AppendFormat("{0}={1}", "content", HttpUtility.UrlEncode("TestQRCode"));
postData.AppendFormat("&{0}={1}", "quality", HttpUtility.UrlEncode("L"));
postData.AppendFormat("&{0}={1}", "type", HttpUtility.UrlEncode("text"));
postData.AppendFormat("&{0}={1}", "size", HttpUtility.UrlEncode("5"));</pre>
<br />
<br />
5. <b>Create Mashape API's URI</b>: This URI responsible to call a specific API listed in Mashape cloud listing. You can get the URL from Mashape site as shown here<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHJ2ez98mrTVSR-eBPhilxqWJ-0PHUGuoxOrCQo6D_cjcPW5yR-_MxXg6chlaeFl1eItnzzWfT40IUnl2Yw2uzfs2eITXeLdZiuIG_8kWOyztVc1VUQvLURQb54RJ0d9sCd2T0L-mNa6HD/s1600/SampleForURI.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img alt="" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHJ2ez98mrTVSR-eBPhilxqWJ-0PHUGuoxOrCQo6D_cjcPW5yR-_MxXg6chlaeFl1eItnzzWfT40IUnl2Yw2uzfs2eITXeLdZiuIG_8kWOyztVc1VUQvLURQb54RJ0d9sCd2T0L-mNa6HD/s1600/SampleForURI.JPG" title="URL To capture from Mashape" /></a><br />
<br />
<pre class="brush:csharp" lang="csharp">var uri = new Uri("https://mutationevent-qr-code-generator.p.mashape.com/generate.php?", UriKind.Absolute);</pre>
<br />
<br />
<b>6.</b> <b>Register a Asyn Call Completed Event</b>:<br />
<br />
<pre class="brush:csharp" lang="csharp">client.UploadStringCompleted += new UploadStringCompletedEventHandler(client_UploadStringCompleted)</pre>
<br />
<br />
7. <b>Make Async http Call:</b><br />
<br />
<pre class="brush:csharp" lang="csharp">client.UploadStringAsync(uri, "POST", postData.ToString());</pre>
<br />
<br />
<b>8. Consume Response in completed event</b>:<br />
<br />
<pre class="brush:csharp" lang="csharp">void client_UploadStringCompleted(object sender, UploadStringCompletedEventArgs e)
{
var client = sender as WebClient;
client.UploadStringCompleted -= client_UploadStringCompleted;
string response = string.Empty;
if (!e.Cancelled)
{
response = HttpUtility.UrlDecode(e.Result);
}
}</pre>
<br />
You are done!!!<br />
<br />
A full working sample can be found at the links given below.<br />
<br />
Source Code: <a href="https://skydrive.live.com/#cid=CB9B95B4DD4D63A6&id=CB9B95B4DD4D63A6%21476" target="_blank">WP7</a>, <a href="https://skydrive.live.com/#cid=CB9B95B4DD4D63A6&id=CB9B95B4DD4D63A6%21477" target="_blank">WP8</a></div>
Nishant Ranahttp://www.blogger.com/profile/04447027857465485472noreply@blogger.com0tag:blogger.com,1999:blog-7841369554122351896.post-51300221605520635522012-09-08T05:35:00.002-07:002012-12-14T22:31:30.604-08:00WP Context Menu using MVVM<div dir="ltr" style="text-align: left;" trbidi="on">When I used <i>ContextMenu</i> in my application for the very first time, my applications were not using <i>MVVM</i>. Therefore, I had to add a context menu either in code behind or using <i>Event Handler</i> in code behind. Now, there were two issues in doing so :<br />
<br />
<div>1. <b>Tedious Code Structure</b> : While adding a context menu from code behind and managing events.</div><div>2. <b>Style Can't be saved to Resource Dictionary </b>: While using <i>Event Handler</i> in xaml you can't define a style in <i>Resource Dictionary</i> because they do not have a code behind file. So you must define the style in your view only. It restrict the modularity of your application.</div><div><br />
</div><div>You can find many good articles about using ContextMenu in code behind. But problem still remains the same. So now how to solve this in more elegant way? And the answer comes with <i>MVVM</i>. </div><div><br />
</div><div>For this article of mine I am using <i><a href="http://www.galasoft.ch/mvvm/" target="_blank">Galasoft-MVVM Light</a>.</i> A handful of useful links: </div><div><ol style="text-align: left;"><li>Download Galasoft-MVVM Light from <a href="http://mvvmlight.codeplex.com/" target="_blank">here</a>. </li>
<li>Alternatively, you can install it from <a href="http://nuget.org/" target="_blank">NuGet</a> (VS extension). </li>
<li>Learn how to install NuGet package from <a href="http://nuget.codeplex.com/wikipage?title=Getting%20Started" target="_blank">here</a>. </li>
</ol></div><div>I am presuming you may have a little understanding of Galasoft's MVVM Light or any other MVVM framework, to better understand this article. </div><div><br />
</div><div>Prerequisite (installed): </div><div>1. NuGet extension for VS.</div><div>2. <a href="http://silverlight.codeplex.com/releases/view/75888" target="_blank">Windows Phone Toolkit - Nov 2011 (7.1 SDK)</a>.</div><div>3. Galasoft-MVVM Light.</div><div><br />
<h2 style="text-align: left;">1. Objective: </h2>We will try to create a ListBox and fill it with some text item(s). Each item in ListBox should have context menu say "READ" on click of that MenuItem we should be able to display the value of selected ListBox item.<br />
<br />
</div><h2 style="text-align: left;"><b>2. Create a New Project:</b> </h2><div>Create a new Project -> Silverlight for Windows Phone -> Mvvm and name it <i>ContextMenu_MVVM</i>.</div><div>Note:- once you have MVVM installed a default template will be available in Installed Templates as shown below. </div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKphsgQyha6u1OtshEdv8oVLIZgsZT1OmzxvZw2f1ZkUPkomZv_j-xdeAwv6J0SynUOZyq_mAY0oMmb7fw1EPRJCndBLG-FzpJmX2FF0AW6ZUisJAPkUpge7ykzMXg6O13DgJQ7BTl4TYP/s1600/CreateProject.JPG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="475" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKphsgQyha6u1OtshEdv8oVLIZgsZT1OmzxvZw2f1ZkUPkomZv_j-xdeAwv6J0SynUOZyq_mAY0oMmb7fw1EPRJCndBLG-FzpJmX2FF0AW6ZUisJAPkUpge7ykzMXg6O13DgJQ7BTl4TYP/s640/CreateProject.JPG" width="640" /></a></div><div><br />
</div><div></div><div><br />
</div><div><br />
</div><div><br />
</div><div><br />
</div><div><br />
</div><div><br />
</div><div><br />
</div><div><br />
</div><div><br />
</div><div><br />
</div><div><br />
</div><div><br />
</div><div><br />
</div><div><br />
</div><div><br />
</div><div><br />
</div><h2 style="text-align: left;"><br />
</h2><h2 style="text-align: left;"><br />
</h2><h2 style="text-align: left;"></h2><h2 style="text-align: left;">3. Adding a Resource Dictionary (Style):</h2><div>Open your project in Expression Blend. Once it's opened in Blend, right click project and Select <i>Add new item</i>. </div><div><br />
</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUH8wiJCRBnc-Q_5D9ESxr12EpT0JtzFnvHuXa1bbePdPyyoX5JkDZR5V2iXZbvPPAPhBCrfWrZJLQe88KBqar0fIs9WCqapLR-anE9rGFGa70BWS-ZvJpPxgD64E-d3QSUfsm8PLyd9Pn/s1600/AddResourceDictionary.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUH8wiJCRBnc-Q_5D9ESxr12EpT0JtzFnvHuXa1bbePdPyyoX5JkDZR5V2iXZbvPPAPhBCrfWrZJLQe88KBqar0fIs9WCqapLR-anE9rGFGa70BWS-ZvJpPxgD64E-d3QSUfsm8PLyd9Pn/s320/AddResourceDictionary.jpg" width="295" /></a></div><div><br />
</div><div><br />
</div><div><br />
</div><div><br />
</div><div><br />
</div><div><br />
</div><div><br />
</div><div><br />
</div><div><br />
</div><div><br />
</div><div><br />
</div><div><br />
</div><div><br />
</div><div><br />
</div><div><br />
</div><div><br />
</div><div><br />
</div><div><br />
</div><div><br />
</div><div><br />
</div><div>Select <i>Resource Dictionary</i> and rename it <i>Styles.xaml</i>(Refer image above).</div><div><br />
</div><div>Now replace the code of Styles.xaml with this code:<br />
<br />
<br />
<pre class="brush:xml" lang="csharp"><resourcedictionary xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<style targettype="ListBoxItem" x:key="ContexMenuItemStyle">
<setter Property="Background" Value="Transparent"/>
<setter Property="BorderThickness" Value="0"/>
<setter Property="BorderBrush" Value="Transparent"/>
<setter Property="Padding" Value="0"/>
<setter Property="HorizontalContentAlignment" Value="Left"/>
<setter Property="VerticalContentAlignment" Value="Top"/>
<setter Property="Template">
<Setter.Value>
<controltemplate TargetType="ListBoxItem">
<border x:Name="LayoutRoot" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" HorizontalAlignment="{TemplateBinding HorizontalAlignment}" VerticalAlignment="{TemplateBinding VerticalAlignment}" DataContext="{Binding Source={StaticResource Locator}}">
<VisualStateManager.VisualStateGroups>
<visualstategroup x:Name="CommonStates">
<visualstate x:Name="Normal"/>
<visualstate x:Name="MouseOver"/>
<visualstate x:Name="Disabled">
<storyboard>
<objectanimationusingkeyframes Storyboard.TargetProperty="Background" Storyboard.TargetName="LayoutRoot">
<discreteobjectkeyframe KeyTime="0" Value="{StaticResource TransparentBrush}"/>
</ObjectAnimationUsingKeyFrames>
<doubleanimation Duration="0" To=".5" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="ContentContainer"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
<visualstategroup x:Name="SelectionStates">
<visualstate x:Name="Unselected"/>
<visualstate x:Name="Selected">
<storyboard>
<objectanimationusingkeyframes Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentContainer">
<discreteobjectkeyframe KeyTime="0" Value="{StaticResource PhoneAccentBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<textblock x:Name="ContentContainer" TextWrapping="Wrap" Text="{TemplateBinding Content}" Width="100" Height="30" HorizontalAlignment="Left">
<toolkit:ContextMenuService.ContextMenu>
<toolkit:ContextMenu>
<toolkit:MenuItem Header="Red" Command="{Binding Main.CTest, Mode=OneWay}" CommandParameter="{TemplateBinding DataContext}"/>
</toolkit:ContextMenu>
</toolkit:ContextMenuService.ContextMenu>
</TextBlock>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</style>
</resourcedictionary></pre></div><br />
<div></div><div>This code contains a necessary style for a <i>ListboxItem,</i> that we are going to use for our demonstration purpose. </div><div><br />
</div><h2 style="text-align: left;"><b>4. Adding Code For MainPage.xaml </b>: </h2><div>In you MainPage.xaml replace code for ContentPanel grid with this one:<br />
<br />
<pre class="brush:csharp" lang="csharp"><!--ContentPanel - place additional content here-->
<grid grid.row="1" x:name="ContentGrid">
<listbox itemcontainerstyle="{StaticResource ContexMenuItemStyle}" itemssource="{Binding CtxItems}" selecteditem="{Binding SelectedCtxItems, Mode=TwoWay}" x:name="lbxTest">
</listbox></grid></pre><br />
<br />
<h2 style="text-align: left;">5. Update Code for MainPage View Model: </h2>In you MainViewModel.cs add this code in using syntax area to include the reference for some namespaces:<br />
<br />
<pre class="brush:csharp" lang="csharp">using GalaSoft.MvvmLight.Command;
using System.Collections.ObjectModel;
using System.Windows;</pre><br />
<br />
Add this code to same page just before you MainViewModel class closes:<br />
<br />
<pre class="brush:csharp" lang="csharp">#region Properties
public RelayCommand<string> CTest { get; private set; }
private ObservableCollection<string> _CtxItems;
public ObservableCollection<string> CtxItems
{
get
{ return _CtxItems; }
set
{
if (_CtxItems == value)
{
return;
}
var oldValue = _CtxItems;
_CtxItems = value;
base.RaisePropertyChanged("CtxItems");
}
}
private string _SelectedCtxItems;
public string SelectedCtxItems
{
get
{ return _SelectedCtxItems; }
set
{
if (_SelectedCtxItems == value)
{
return;
}
var oldValue = _SelectedCtxItems;
_SelectedCtxItems = value;
base.RaisePropertyChanged("SelectedCtxItems");
}
}
#endregion
#region Methods
private void LoadData()
{
CtxItems = new ObservableCollection<string>();
for (int i = 0; i < 10; i++)
{
CtxItems.Add("Item " + i.ToString());
}
}
private void Test(string data)
{
MessageBox.Show(data);
}
#endregion</string></string></string></string></pre></div><div><br />
This code contains all the logic for populating your ListBox and RelayCommands used for doing command binding.<br />
<br />
Add following code to MaiViewModel constructor to initialize the collection that we placed in code above.<br />
<br />
<pre class="brush:csharp" lang="csharp">public MainViewModel()
{
if (IsInDesignMode)
{
// Code runs in Blend --> create design time data.
}
else
{
LoadData();
CTest = new RelayCommand<string>(Test);
}
}</string></pre><br />
<h2 style="text-align: left;">6. Working :</h2><h4 style="text-align: left;">Style:</h4><div>A style for <i>ListBox</i> item is defined in <i>styles.xaml</i> which contains a <i>Textbox</i> which has a <i>ContextMenu</i>. For this <i>ContextMenu</i> we have bound its property called <i><b>Command</b></i> to <i><a href="http://blog.galasoft.ch/archive/2009/09/26/using-relaycommands-in-silverlight-and-wpf.aspx" target="_blank">Relay Command</a> </i>i.e. <i>CTest</i> in <i>MainViewModel</i>. Also we are binding <i><b>CommandParameter</b> </i>property of <i>ContextMenu</i> with <i><b>Templated DataContext</b></i> to insure we get currently selected item in our view-model. </div><div><br />
</div><h4 style="text-align: left;">ViewModel: </h4><div>It contains 4 items:</div><div><ol style="text-align: left;"><li><b><i>CTest</i></b>: A property that will expose a relay command to enable binding to our view. </li>
<li><b><i>CtxItems</i></b>: A property that provides ann <i><a href="http://msdn.microsoft.com/en-us/library/ms668604.aspx" target="_blank">ObservableCollection</a></i> that contains items to be listed in ListBox. </li>
<li><b><i>LoadData</i></b>: Methods to initialize CtxItems. </li>
<li><b><i>Test</i></b>: An <a href="http://msdn.microsoft.com/en-us/library/018hxwa8.aspx" target="_blank">Action </a>that need to be passed in as an argument for relay command while initializing command. </li>
</ol></div>A full source code link is given below for reference.<br />
<br />
<a href="https://skydrive.live.com/#cid=CB9B95B4DD4D63A6&id=CB9B95B4DD4D63A6%21415" target="_blank">Source Code</a><br />
<br />
</div><div>Thanks and Regards</div><div>Nishant Rana</div><div><br />
</div></div>Nishant Ranahttp://www.blogger.com/profile/04447027857465485472noreply@blogger.com0tag:blogger.com,1999:blog-7841369554122351896.post-61487639887371690252011-12-29T08:19:00.001-08:002012-12-14T22:33:05.302-08:00Add Scrolling Event in a List - WP7<div dir="ltr" style="text-align: left;" trbidi="on">Many of you might have been in a situation when you desperately wanted to know if a scroll bar is scrolling or not.<br />
<br />
Currently there is no direct provision to attain this in WP7. I'll walk through the code which will help you to identify if a list is scrolling or not. Later at the end there ia a full working sample attached.<br />
<br />
My sample is straight forward. I'll be changing the page title to "Scrolling" when we scroll the list and "NotScrolling" while it is stationary.<br />
<br />
We have a list called <b>theList</b>.<br />
<br />
<b>1</b>. <b>Now attach a Loaded event to the page constructor</b>:<br />
<br />
<pre class="brush:csharp" lang="csharp">public MainPage()
{
InitializeComponent();
Loaded += new RoutedEventHandler(MainPage_Loaded);
theList.ItemsSource = GetListData(60);
}</pre><br />
<b>2</b>. <b>Define a variable to identify if ScrollEvent has been hooked already</b>:<br />
<br />
<pre class="brush:csharp" lang="csharp">bool alreadyHookedScrollEvents = false;</pre><br />
<b>3.</b> <b>Define MainPage_Loaded handler. All major work will be done here</b>:<br />
<br />
<pre class="brush:csharp" lang="csharp">void MainPage_Loaded(object sender, RoutedEventArgs e)
{
if (alreadyHookedScrollEvents)
return;
alreadyHookedScrollEvents = true;
//This is the key player which holds the magic for this trick
//This ScrollViewer is the first templated child of your List
ScrollViewer viewer = FindSimpleVisualChild<ScrollViewer>(theList);
if (viewer != null)
{
// Visual States are always on the first child of the control template
FrameworkElement element = VisualTreeHelper.GetChild(viewer, 0) as FrameworkElement;
if (element != null)
{
VisualStateGroup group = FindVisualState(element, "ScrollStates");
if (group != null)
{
group.CurrentStateChanging += group_CurrentStateChanging;
}
}
}
}</pre><br />
<b>4.</b> <b>Use this helper function to identify the first visual child (ScrollViewer)</b>:<br />
<br />
<pre class="brush:csharp" lang="csharp">T FindSimpleVisualChild<T>(DependencyObject element) where T : class
{
while (element != null)
{
if (element is T)
return element as T;
element = VisualTreeHelper.GetChild(element, 0);
}
return null;
}</pre><br />
<b>5</b>. <b>Actual even handler which identify a changed state for scrollviewer</b>:<br />
<br />
<pre class="brush:csharp" lang="csharp">void group_CurrentStateChanging(object sender, VisualStateChangedEventArgs e)
{
//for demonstration change page's title
PageTitle.Text = e.NewState.Name;
}</pre><br />
<b>6</b>. <b>Helper function to filter out the required VisualState</b>:<br />
<br />
<br />
<pre class="brush:csharp" lang="csharp">VisualStateGroup FindVisualState(FrameworkElement element, string name)
{
if (element == null)
return null;
IList<VisualStateGroup> groups = (IList<VisualStateGroup>)VisualStateManager.GetVisualStateGroups(element);
foreach (VisualStateGroup group in groups)
if (group.Name == name)
return group;
return null;
}</pre><br />
<br />
<b>7.</b> <b>Another helper function to fill the data in list to demonstrate implementation</b>:<br />
<br />
<br />
<pre class="brush:csharp" lang="csharp">ObservableCollection<int> GetListData(int count)
{
sourceList = new ObservableCollection<int>();
for (int i = 1; i <= count; i++)
{
sourceList.Add(i);
}
return sourceList;
}</pre><br />
<br />
<a href="https://skydrive.live.com/?cid=cb9b95b4dd4d63a6#cid=CB9B95B4DD4D63A6&id=CB9B95B4DD4D63A6%21302" target="_blank">Source Code</a><br />
<br />
</div>Nishant Ranahttp://www.blogger.com/profile/04447027857465485472noreply@blogger.com0tag:blogger.com,1999:blog-7841369554122351896.post-11410872172226391202011-09-29T01:09:00.000-07:002011-09-29T01:09:17.688-07:00Windows Phone 7 and Emulator Shortcut Keys<div dir="ltr" style="text-align: left;" trbidi="on">
<div>
<span class="Apple-style-span" style="background-color: white; font-family: Verdana, Geneva, sans-serif; font-size: 12px; line-height: 18px;"><table border="1" cellpadding="0" cellspacing="0" style="border-bottom-style: none; border-color: initial; border-left-style: none; border-right-style: none; border-top-style: none; border-width: initial;"><tbody>
<tr><td style="border-bottom-style: none; border-color: initial; border-left-style: none; border-right-style: none; border-top-style: none; border-width: initial;" valign="top" width="127"><strong style="font-weight: bold;">Key</strong></td><td style="border-bottom-style: none; border-color: initial; border-left-style: none; border-right-style: none; border-top-style: none; border-width: initial;" valign="top" width="511"><strong style="font-weight: bold;">Description</strong></td></tr>
<tr><td style="border-bottom-style: none; border-color: initial; border-left-style: none; border-right-style: none; border-top-style: none; border-width: initial;" valign="top" width="127"><strong style="font-weight: bold;">F1</strong><strong style="font-weight: bold;"></strong></td><td style="border-bottom-style: none; border-color: initial; border-left-style: none; border-right-style: none; border-top-style: none; border-width: initial;" valign="top" width="511">Use F1 key on the keyboard instead of back button on the phone</td></tr>
<tr><td style="border-bottom-style: none; border-color: initial; border-left-style: none; border-right-style: none; border-top-style: none; border-width: initial;" valign="top" width="127"><strong style="font-weight: bold;">F2</strong><strong style="font-weight: bold;"></strong></td><td style="border-bottom-style: none; border-color: initial; border-left-style: none; border-right-style: none; border-top-style: none; border-width: initial;" valign="top" width="511">Use the key F2 on the keyboard for the Windows key in the Windows Phone 7</td></tr>
<tr><td style="border-bottom-style: none; border-color: initial; border-left-style: none; border-right-style: none; border-top-style: none; border-width: initial;" valign="top" width="127"><strong style="font-weight: bold;">Pageup</strong></td><td style="border-bottom-style: none; border-color: initial; border-left-style: none; border-right-style: none; border-top-style: none; border-width: initial;" valign="top" width="511">Enables the keyboard in the emulator when the focus is on the textbox</td></tr>
<tr><td style="border-bottom-style: none; border-color: initial; border-left-style: none; border-right-style: none; border-top-style: none; border-width: initial;" valign="top" width="127"><strong style="font-weight: bold;">PageDown</strong></td><td style="border-bottom-style: none; border-color: initial; border-left-style: none; border-right-style: none; border-top-style: none; border-width: initial;" valign="top" width="511">Disables the keyboard in the emulator</td></tr>
<tr><td style="border-bottom-style: none; border-color: initial; border-left-style: none; border-right-style: none; border-top-style: none; border-width: initial;" valign="top" width="127"><strong style="font-weight: bold;">F3</strong></td><td style="border-bottom-style: none; border-color: initial; border-left-style: none; border-right-style: none; border-top-style: none; border-width: initial;" valign="top" width="511">To open the Bing Search</td></tr>
<tr><td style="border-bottom-style: none; border-color: initial; border-left-style: none; border-right-style: none; border-top-style: none; border-width: initial;" valign="top" width="127"><strong style="font-weight: bold;">F7</strong></td><td style="border-bottom-style: none; border-color: initial; border-left-style: none; border-right-style: none; border-top-style: none; border-width: initial;" valign="top" width="511">To Activate the Physical Camera</td></tr>
<tr><td style="border-bottom-style: none; border-color: initial; border-left-style: none; border-right-style: none; border-top-style: none; border-width: initial;" valign="top" width="127"><strong style="font-weight: bold;">F9</strong></td><td style="border-bottom-style: none; border-color: initial; border-left-style: none; border-right-style: none; border-top-style: none; border-width: initial;" valign="top" width="511">Increase the Volume</td></tr>
<tr><td style="border-bottom-style: none; border-color: initial; border-left-style: none; border-right-style: none; border-top-style: none; border-width: initial;" valign="top" width="127"><strong style="font-weight: bold;">F10</strong></td><td style="border-bottom-style: none; border-color: initial; border-left-style: none; border-right-style: none; border-top-style: none; border-width: initial;" valign="top" width="511">Decrease the volume</td></tr>
</tbody></table>
</span></div>
<div>
<br /></div>
<div>
Additional link from <a href="http://msdn.microsoft.com/en-us/library/ff754352%28v=VS.92%29.aspx">MSDN</a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
</div>
Nishant Ranahttp://www.blogger.com/profile/04447027857465485472noreply@blogger.com0tag:blogger.com,1999:blog-7841369554122351896.post-72923580632750867652011-08-25T09:38:00.000-07:002012-12-14T22:34:51.386-08:00Passing Data between Pages in Windows Phone 7<div dir="ltr" style="text-align: left;" trbidi="on"><br />
<div dir="ltr" trbidi="on">Passing data among pages is something which needs to be given a little care in terms what approach you follow . Since each approach has its own benefits and side effects. I'll try to explain each of them one by one.<br />
<br />
For illustration of this concept I've created a sample code which is attached at the end of the article. In this project I've various project each corresponds to one approach which I've described below. Each project has two pages. Touching on the coloured part of one page takes you to another page. First page will display a text string which is provided by the second page. You can simply go to second page add some text into <b>TextBox </b>and you can touch the coloured part to go back to first page which displays the string which you entered on first page.<br />
<br />
So here are the approaches one by one:<br />
<br />
<span class="Apple-style-span" style="color: #b45f06;"><b>1.</b> <b><u>Using Global Variable</u></b>:</span> This is the easiest and quickest procedure to pass your data among various pages.<br />
<br />
<b><i>Define a "Global Variable" in your App.xaml file as</i></b>:<br />
<pre class="brush:csharp" lang="csharp">public string SecondPageText { get; set; }</pre><br />
<b><i>After that on your Second page on ManipulationStarted event for the coloured Border use this code:</i></b><br />
<pre class="brush:csharp" lang="csharp">App.Current as App).SecondPageText = txtBox.Text; // add value to Global variable
NavigationService.GoBack(); // Navigate to first page</pre><br />
<b><i>PhonePageOne page add this:</i></b><br />
<pre class="brush:csharp" lang="csharp">protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
txtBlock.Text = (App.Current as App).SecondPageText;
}</pre></div><span class="Apple-style-span" style="color: #b45f06;"><b><br />
</b></span> <span class="Apple-style-span" style="color: #b45f06;"><b>2.</b> <b><u>Using Query String</u></b>:</span> This procedure is good when we just need to share string based data between two pages.<br />
<br />
<b><i>Add this code in your PhonePageTwo:</i></b><br />
<pre class="brush:csharp" lang="csharp">private void Border_ManipulationStarted(object sender, System.Windows.Input.ManipulationStartedEventArgs e)
{
string uri = "/PhonePageOne.xaml?Text=";
uri += txtBox.Text;
NavigationService.Navigate(new Uri(uri, UriKind.Relative));
}</pre><br />
<b><i>Use this code in your PhonePageTwo:</i></b><br />
<br />
<pre class="brush:csharp" lang="csharp">protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
IDictionary<string, string> parameters = this.NavigationContext.QueryString;
if (parameters.ContainsKey("Text"))
{
txtBlock.Text = parameters["Text"];
}
}</pre><br />
<span class="Apple-style-span" style="color: #b45f06;"><b>3.</b> <b><u>Using PhoneApplicationSerivce States</u></b>:</span> Every application has a PhoneApplicationService defined Microsoft.Phone.Shell. Each application has one PhoneApplicationService defined in its App.xaml file. We can use this service's property called "State". These "States" are all transient data which means they are available only for one instant of your application which means once you restart your application these states will be lost. Also we should not try to create a new PhoneApplicationService instead we must try to use the service from the current instant. Which can be retrieved using this code:<br />
<br />
<b>PhoneApplicationService.Current.State</b><br />
<br />
Now, lets look how can we really use it in our sample.<br />
<br />
<b><i>PhonePageTwo add this code:</i></b><br />
<br />
<pre class="brush:csharp" lang="csharp">protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
PhoneApplicationService.Current.State["Text"] = txtBox.Text;
}
private void Border_ManipulationStarted(object sender, System.Windows.Input.ManipulationStartedEventArgs e)
{
NavigationService.GoBack();
}</pre><br />
<b><i>PhonePageOne add this code:</i></b><br />
<br />
<pre class="brush:csharp" lang="csharp">private void LayoutRoot_ManipulationStarted(object sender, System.Windows.Input.ManipulationStartedEventArgs e)
{
NavigationService.Navigate(new Uri("/PhonePageTwo.xaml", UriKind.Relative));
}
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
if(PhoneApplicationService.Current.State.ContainsKey("Text"))
txtBlock.Text = (string)PhoneApplicationService.Current.State["Text"];
}</pre><br />
<span class="Apple-style-span" style="color: #b45f06;"><b>4.</b> <b><u>Using NextPage intance</u></b>:</span> Whenever we call "<i>Navigate</i>" using a "/PageOne.xaml" or "/PageTwo.xaml" the <i>OnNavigatedFrom </i>method in current page is called with event arguments with a <i>Uri </i>property indicating other page and a <i>Content</i> property of type that page (<i>Navigating to</i>) . After that <i>OnNavigatedTo</i> of other page will be called with same arguments. So we have an opportunity to fix the set the value for next page prior to navigating to it. Just take a look at the sample code:<br />
<br />
<b><i>PageTwo add this code:</i></b><br />
<br />
<pre class="brush:csharp" lang="csharp">protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
if (e.Content is PageOne)
{
(e.Content as PageOne).txtBlock.Text = txtBox.Text;
}
}
private void Border_ManipulationStarted(object sender, System.Windows.Input.ManipulationStartedEventArgs e)
{
NavigationService.GoBack();
}</pre><br />
<b><i>PageOne add this code</i>: (</b>Basically no need to do any thing just use this)<br />
<br />
<pre class="brush:csharp" lang="csharp">private void LayoutRoot_ManipulationStarted(object sender, System.Windows.Input.ManipulationStartedEventArgs e)
{
NavigationService.Navigate(new Uri("/PageTwo.xaml", UriKind.Relative));
}
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
}</pre><br />
<br />
<span class="Apple-style-span" style="color: orange;"><a href="https://skydrive.live.com/#!/?cid=cb9b95b4dd4d63a6&sc=documents&uc=1&id=CB9B95B4DD4D63A6%21230">Source Cod</a></span><br />
</div>Nishant Ranahttp://www.blogger.com/profile/04447027857465485472noreply@blogger.com15tag:blogger.com,1999:blog-7841369554122351896.post-84390749194209831892011-08-02T02:30:00.000-07:002012-12-14T22:35:59.951-08:00Access Templated Child in Silverlight and Windows Phone 7<div dir="ltr" style="text-align: left;" trbidi="on"><br />
<br class="Apple-interchange-newline" /> Accessing a templated child is way too simple in WPF but for SilverLight which is even being used in Windows Phone 7 needs a little extra work to the work being done. Well there are two ways to achieve it. I'll try to explain both of them one by one. Before getting into explanations of these methods we need a sample template to get a better picture.<br />
<br />
<b>A sample template for a ListBoxItem</b> :<br />
<br />
<pre class="brush:csharp" lang="csharp"><style targettype="ListBoxItem" x:key="ListBoxItemStyle">
<setter Property="Background" Value="Transparent"/>
<setter Property="BorderThickness" Value="0"/>
<setter Property="BorderBrush" Value="Transparent"/>
<setter Property="Padding" Value="0"/>
<setter Property="HorizontalContentAlignment" Value="Left"/>
<setter Property="VerticalContentAlignment" Value="Top"/>
<setter Property="Template">
<Setter.Value>
<controltemplate TargetType="ListBoxItem">
<stackpanel>
<textblock x:Name="myTextBlk" Text="Static Text To Change" Foreground="White"/>
<textblock Text="{Binding}" TextWrapping="Wrap" HorizontalAlignment="Center" VerticalAlignment="Center" Width="80" Height="72"/>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</style></pre><br />
So, now when we have custom style :-) we can start looking into the options to retrieve an element (<b>myTextBox</b>) from Style at run time.<br />
<div><b><br />
</b></div><div><b><u>First Approach</u></b>: </div><div><ol><li> Make sure you have defined names for the items you are going to acess in your template let say it "myTextBox".</li>
<li>Now you must have ListBoxItem for which you are going to find your TemplateChild lets say it "lbi".</li>
</ol>After going through these initial check now use the following code to find element:<br />
<br />
<pre class="brush:csharp" lang="csharp">//Enforce Style to apply in case if it's not yet applied
lbi.ApplyTemplate();
FirstApproach(lbi);
void FirstApproach(ListBoxItem lbi)
{
StackPanel stkTemplatedChild = VisualTreeHelper.GetChild((DependencyObject)lbi, 0) as StackPanel;
TextBlock txtBlk = stkTemplatedChild.FindName("myTextBlk") as TextBlock;
txtBlk.Text = "First Approach CLicked";
}</pre></div><div><br />
<span style="font-size: 11px;"></span></div><div>So, "<b>txtBlk </b>" is your desired element </div><div><br />
</div><div><b><u>Second Approach</u></b>:</div><div><br />
</div><div>This approach is to itrerate through all the elements in style's template. which can be done by using this code:<br />
<br />
<pre class="brush:csharp" lang="csharp">//Enforce Style to apply in case if it's not yet applied
lbi.ApplyTemplate();
SecondApproach(lbi);
void SecondApproach(ListBoxItem lbi)
{
TextBlock templatedTextBlk;
int childCount = VisualTreeHelper.GetChildrenCount((DependencyObject)lbi);
for (int i = 0; i < childCount; i++)
{
DependencyObject childObj = VisualTreeHelper.GetChild(lbi, i);
int subChild = VisualTreeHelper.GetChildrenCount(childObj);
for (int n = 0; n < subChild; n++)
{
DependencyObject dpChild = VisualTreeHelper.GetChild(childObj, n);
if (dpChild is TextBlock && (dpChild as TextBlock).Name == "myTextBlk")
{
templatedTextBlk = dpChild as TextBlock;
templatedTextBlk.Text = "Second Approach Clicked";
break;
}
}
}
}</pre></div><div>"<b>templatedTextBx</b>" is your result.<br />
<br />
<b><u>Third Approach (using helper function)</u></b>: This approach may look catchy but it has some down sides. In this approach you have to iterate through VisualTree which could be a resource intensive. But this one is good if you have a inline template.<br />
<br />
<pre class="brush:csharp" lang="csharp">//Enforce Style to apply in case if it's not yet applied
lbi.ApplyTemplate();
TextBlock txtbx = FindVisualChildByType<textblock>(lbi, "myTextBlk");
if (txtbx != null)
txtbx.Text = "Third Approach Clicked";
T FindVisualChildByType<t>(DependencyObject element, String name) where T : class
{
if (element is T && (element as FrameworkElement).Name == name)
return element as T;
int childcount = VisualTreeHelper.GetChildrenCount(element);
for (int i = 0; i < childcount; i++)
{
T childElement = FindVisualChildByType<t>(VisualTreeHelper.GetChild(element, i), name);
if (childElement != null)
return childElement;
}
return null;
}</t></t></textblock></pre>So, <i>txtbx</i> is your desired result.<br />
<b><a href="https://skydrive.live.com/?cid=cb9b95b4dd4d63a6&sc=documents&uc=1&id=CB9B95B4DD4D63A6%21215">Source Code</a></b></div></div>Nishant Ranahttp://www.blogger.com/profile/04447027857465485472noreply@blogger.com4