Posts Tagged ‘Silverlight’

.Net, Silverlight Silverlight – Custom ListBox Item Template

8 Comments

In this tutorial, I will show how to create a custom ListBox Item Template.

For anybody who has tried doing a custom Item Template in WinForms, you would know that it is not fun. You have to override Draw/Paint events, and other jazz to get a ListBox to show how you want it to. However, in Silverlight/WPF, this process is so much easier.

I will be using Blend 4 in my example, as Blend makes the process even more easier.

So first we are going to create a Silverlight project. I will name it CustomListBoxItemTemplate.

10-24-2010 8-46-18 AM

Next, we are going to add a ListBox to our page. I made mine with a Height of 250, and a Width of 300, and gave it the name lstPeople.

<ListBox
   x:Name="lstPeople"
   ItemsSource="{Binding}"
   DisplayMemberPath="FullName"
   Margin="145,92,195,138"/>

Before we get to styling the ListBox, we need to create some test data to load into our ListBox. I created a simply Person class.

public class Person
{
    // Insert code required on object creation below this point.
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }
    public string FullName { get { return FirstName + " " + LastName; } }

    public Person(string _fName, string _lName, int _age)
    {
        FirstName = _fName;
        LastName = _lName;
        Age = _age;
    }
}

And add it to the ListBox…

public partial class MainPage : UserControl
{
	public MainPage()
	{
	     // Required to initialize variables
	     InitializeComponent();

             ObservableCollection<Person> peopleList = new ObservableCollection<Person>();
             peopleList.Add(new Person("John", "Doe", 32));
             peopleList.Add(new Person("Jane", "Doe", 20));
             peopleList.Add(new Person("Betty", "Sue", 65));

             lstPeople.ItemsSource = peopleList;
	}
}

So now, our ListBox looks like this…

10-24-2010 9-12-12 AM

Let’s say that we want to display the age below the Full Name. We can use Blend to edit the Item Template of the ListBox.

In the Objects And Timeline window, right-click on the ListBox –> Edit Additional Templates –> Edit Generated Items(ItemTemplate) –> Create Empty. You could also use the “Edit A Copy” if it’s available.

10-24-2010 9-16-07 AM

We will name it MyListBoxItemTemplate.

10-24-2010 9-16-54 AM

If you switch over to the XAML view, you will see that the ItemTemplate of the ListBox has now been binded to a Static Resource. Right above the LayoutRoot in the UserControl.Resources, you should a DataTemplate.

You will now see a small Grid on the screen. We will expand the grid to a Height of 55 and a Width of 225. Inside the grid, we are going to add 4 TextBlocks. Two will be for display purposes and the other two will show our information. Notice I am also Binding the FullName and Age properties to the Text property of the TextBlock.

<Grid Width="225" Height="55">

	<TextBlock
		Text="Full Name:"
		HorizontalAlignment="Left"
		Height="15"
		Margin="12,8,0,0"
		TextWrapping="Wrap"
		VerticalAlignment="Top"
		Width="70"/>

	<TextBlock
		Text="Age:"
		HorizontalAlignment="Left"
		Margin="46,27,0,13"
		TextWrapping="Wrap"
		Width="33"/>

	<TextBlock
		x:Name="FullNameTextBlock"
		Text="{Binding FullName}"
		Height="15"
		Margin="86,8,8,0"
		TextWrapping="Wrap"
		VerticalAlignment="Top" />

	<TextBlock
		x:Name="AgeTextBlock"
		Text="{Binding Age}"
		Margin="86,27,92,13"
		TextWrapping="Wrap" />

</Grid>

And that’s all we need to do. To get out of the ItemTemplate editing, click on the ListBox at the top…

10-24-2010 9-32-30 AM

Now run the application, and your ListBox will now look like this…

10-24-2010 9-32-45 AM

As you can see, using Blend in a Silverlight or WPF application, you can customize a ListBox in only a few minutes.

<ListBox
x:Name=”lstPeople”
ItemsSource=”{Binding}”
DisplayMemberPath=”FullName”
Margin=”145,92,195,138″/>
Tags: , , ,

Silverlight Silverlight 4 – Using The Visual State Manager And Behaviors

4 Comments

In this tutorial, I am going to use the Visual State Manager and Behaviors to do animations. I will be using Blend 4 to do this tutorial. Blend will make this much easier to do rather than writing the XAML by hand.


The Visual State Manager allows you to create “states” of objects and then move to those states. Moving to those states can be done through code(just one line of code), or by using behaviors.

NOTE: The VisualStateManager was added in Silverlight 2. However, it wasn’t included in WPF until .Net 4. To use the VisualStateManager in WPF in .Net 3.5 SP1, you will need to download the WPF Toolkit from CodePlex.

So first, we will create a new project in Blend. We will just create a Silverlight 4 application without the website. We will name the project
VisualStateExample.

9-12-2010 9-36-57 AM

We will now draw a Rectangle on our page, and give it a Fill of Blue.

9-12-2010 9-39-35 AM 9-12-2010 9-42-18 AM


9-12-2010 9-41-19 AM

Next, we are going to go to the States tab.

9-12-2010 9-44-56 AM

This is where we will create all of our states.

So first, we need to create a State Group. Click the
Add State Group button, name it MyStateGroup, then give it a default transition time of 0.4s.

9-12-2010 9-47-41 AM

9-12-2010 9-48-37 AM

Now that we have our State Group, we need to create our individual states. Let’s say that we want the rectangle to change colors when the mouse hovers over it. When the mouse moves away, we want it to change back to it’s original color. Also, let’s change the color when the left mouse button is held down on the rectangle(Mouse Down), then change back when the left mouse button is released(Mouse Up).

So let’s create our first state. Our first state will be our current, default state. Click the
Add State button, then name it MouseOutState.

9-12-2010 9-48-37 AM

9-12-2010 9-55-30 AM

If you notice, now there is a red rectangle around the designer. This means that you are currently in recording mode for the state. ANY changes that are made in the designer will be recorded for that state. Clicking on the Base state will stop recording.

Since this is our default state, we don’t need to record anything.

Now, create another state named
MouseOverState. While still in recording mode, select the Rectangle from the Objects and Timeline tab, and change it’s Fill color to Orange. Click on the Base state to stop recording.

9-12-2010 9-58-42 AM

9-12-2010 10-01-16 AM

9-12-2010 10-02-30 AM

Now, create another state named MouseDownState. While still in recording mode, change it’s Fill color to Green.

9-12-2010 10-09-08 AM

9-12-2010 10-09-33 AM

Now, we need to create our last state. Create a new state and name it MouseUpState. While still in recording mode, change the Fill color to the Orange from the MouseOverState.

We should now have 4 states. Now we need to go to these states with the mouse events. There are a couple of ways of doing this, but I will use
behaviors to do it.

There are a number of behaviors in Blend, and we are going to use the
GoToStateAction behavior.

Go to the
Assets tab, then click on behaviors, then click on the GoToStateAction.

9-12-2010 10-15-22 AM

Now drag that action onto the Rectange in the designer. You will now see that the GoToStateAction has been added to the Rectangle in the Objects and Timeline tab.

9-12-2010 10-19-13 AM

With the GoToStateAction selected, go to the Properties tab, set the EventName to MouseEnter, and set StateName to MouseOverState.

9-12-2010 10-20-29 AM

Do these steps to create a GoToStateAction for the other three states that we have. When you have completed, you will have four actions for the Rectangle.

9-12-2010 10-23-54 AM

You have now finished the animations. Run the application using F5, and move the mouse over the rectangle. Perform the other mouse actions to see the other animations.

This is just another way the Expression Blend makes animations so easy. I have created animations without writing one line of code. To me, that’s pretty amazing and can make application development much quicker and have less bugs.

Tags: , ,

.Net, Silverlight WP7 – Context Menu From Listbox

2 Comments

In writing one of my Windows Phone 7 applications, I needed to do a allow the user to delete an entry from a ListBox. Since my ListBox didn’t have enough room for an actual delete button, I decided I would use a ContextMenu to do it. To my surprise, even though the OS seems to support a long press action(the way to uninstall an application), that action doesn’t seem to be available to developers(or not that I could find). So I decided to roll my own using the [b]MouseLeftButtonDown [/b]and [b]MouseLeftButtonUp [/b]events, and a [b]DispatcherTimer[/b]. Add these two using statements to the top of the code…
 using System.Collections.ObjectModel; using System.Windows.Threading; 

So first, we need our initial code to get the [b]ListBox [/b]populated. I created a [b]Person [/b]class just for simplistic reasons.

 public class Person {     public string FirstName { get; set; }     public string LastName { get; set; } } 

Next, I will set up the [b]ListBox [/b]to simply show the [b]FirstName [/b]of the [b]Person[/b].

 <ListBox      Name="lbNames"      Height="240"      HorizontalAlignment="Left"      Margin="10,119,0,0"      VerticalAlignment="Top"      Width="460"     ItemsSource="{Binding}">                      <ListBox.ItemTemplate>         <DataTemplate>             <StackPanel>                 <TextBlock Text="{Binding FirstName}" />             </StackPanel>         </DataTemplate>     </ListBox.ItemTemplate>                  </ListBox> 

Now I will create an generic [b]ObservableCollection [/b]object to store the [b]Person [/b]objects. This will be a class level variable since it will be accessed from multiple events.

 public partial class MainPage : PhoneApplicationPage {     ObservableCollection<Person> personList = new ObservableCollection<Person>();      // Constructor     public MainPage()     {         InitializeComponent();          this.Loaded += new RoutedEventHandler(MainPage_Loaded);     }      void MainPage_Loaded(object sender, RoutedEventArgs e)     {         personList.Add(new Person() { FirstName = "John", LastName = "Doe" });         personList.Add(new Person() { FirstName = "Jane", LastName = "Doe" });         personList.Add(new Person() { FirstName = "John", LastName = "Adams" });          lbNames.ItemsSource = personList;     } } 

Now I need to create the event handlers for the [b]MouseLeftButtonDown [/b]and [b]MouseLeftButtonUp [/b]events. This can simply be done by using the [b]Events [/b]list from the [b]Properties [/b]window in the designer.

 private void lbNames_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e) {  }  private void lbNames_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e) {  } 

We now need to create two class level objects: a [b]DispatcherTimer [/b]object, and a [b]Person [/b]object. These are class level because they will need to be accessed from different events. We will also subscribe to the Tick event for the timer.

 ObservableCollection<Person> personList = new ObservableCollection<Person>();  DispatcherTimer timer;  Person selectedPerson = null;  // Constructor public MainPage() {     InitializeComponent();      this.Loaded += new RoutedEventHandler(MainPage_Loaded);      timer = new DispatcherTimer();     timer.Tick += delegate(object s, EventArgs e)     {      }; } 

Next, we will add a [b]Popup [/b]in XAML. This can go above or below the [b]ListBox[/b] that is currently holding the names.

 <Popup      x:Name="DeleteContextMenu"      Height="200"      Width="400">      <!-- This is a ListBox as an ItemTemplate for the Popup -->     <ListBox          x:Name="lbDeleteContextMenu"         Background="White"         SelectionChanged="DeleteContextMenu_SelectionChanged">          <ListBoxItem             Content="Delete Person"              Foreground="Red"             FontSize="25"             FontWeight="Bold"/>      </ListBox>  </Popup> 

And the event handler for selecting the Delete item…

 private void DeleteContextMenu_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e) {  } 

Here is how it’s going to work. When the user presses down, we will start the timer. When the user releases, then we stop the timer. So if the timer’s interval is reached, we know that the user was holding down on the screen, so we will display the popup. So now we move to our code. First we are going to handle the [b]MouseLeftButtonDown [/b]event.

 private void lbNames_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e) {     // if there is no person selected, then there is no person to delete     //   no need to do any code if nothing is selected     if (selectedPerson == null)         return;      // gets the position of the mouse cursor to set the Margin     //    of the Popup to show at the mouse coordinates.  You     //    may need to tweak these values to get it to display in     //    the correct location.     Point position = e.GetPosition((UIElement)this);     DeleteContextMenu.Margin = new Thickness(position.X, position.Y - 200, 20, 0);      // sets the interval to 1.1 seconds.  This means the user will need      //    to hold down on the screen for 1.1 seconds before we determine     //    to show the ContextMenu.     timer.Interval = TimeSpan.FromMilliseconds(1100);     timer.Start(); } 

Next, we will do our code for the [b]MouseLeftButtonUp[/b] event

 private void lbNames_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e) {     // stop the timer when the user releases the screen     timer.Stop();      // sets the class level variable to the selected row     selectedPerson = lbNames.SelectedItem as Person; } 

Now for our code in the [b]Tick [/b]event for the [b]Timer[/b].

 // Constructor public MainPage() {     InitializeComponent();      this.Loaded += new RoutedEventHandler(MainPage_Loaded);      timer = new DispatcherTimer();     timer.Tick += delegate(object s, EventArgs e)     {         // stop the timer so that it doesn't popup the Context menu again         timer.Stop();          // since we are using the same ListBox over and over, this will         //   make it so when the Context Menu is shown, there will be no         //   selected item from any previous showing of the Context Menu         lbDeleteContextMenu.SelectedIndex = -1;          // opens the Context Menu         DeleteContextMenu.IsOpen = true;     }; } 

Last, we have our code from the [b]SelectionChanged [/b]event for the [b]ListBox [/b]that is part of the Context Menu.

 private void DeleteContextMenu_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e) {     // in the Timer's Tick event, we set the SelectedIndex of the     //   Context Menu's Listbox back to -1.  However, this does     //   fire the SelectionChanged event.  This code will handle that.     if (lbDeleteContextMenu.SelectedIndex == -1)         return;      // closes the Context Menu     DeleteContextMenu.IsOpen = false;      if (selectedPerson == null)         return;      // removes the selected person from the list     personList.Remove(selectedPerson);      // since we are using an ObservableCollection, we do not have     //   to rebind the list to the ListBox.      selectedPerson = null; } 

Now you can run the application, and you will see the list show up. You must click on an item first before clicking and holding to show the Context Menu.

In writing one of my Windows Phone 7 applications, I needed to do a allow the user to delete an entry from a ListBox.  Since my ListBox didn’t have enough room for an actual delete button, I decided I would use a ContextMenu to do it.  To my surprise, even though the OS seems to support a long press action(the way to uninstall an application), that action doesn’t seem to be available to developers(or not that I could find).
So I decided to roll my own using the [b]MouseLeftButtonDown [/b]and [b]MouseLeftButtonUp [/b]events, and a [b]DispatcherTimer[/b].
Add these two using statements to the top of the code…
</pre>
</div>
<div>using System.Collections.ObjectModel;</div>
<div>using System.Windows.Threading;</div>
<div>
So first, we need our initial code to get the [b]ListBox [/b]populated.  I created a [b]Person [/b]class just for simplistic reasons.
</pre>
</div>
<div>public class Person</div>
<div>{</div>
<div>public string FirstName { get; set; }</div>
<div>public string LastName { get; set; }</div>
<div>}</div>
<div>
Next, I will set up the [b]ListBox [/b]to simply show the [b]FirstName [/b]of the [b]Person[/b].
</pre>
</div>
<div><ListBox</div>
<div>Name="lbNames"</div>
<div>Height="240"</div>
<div>HorizontalAlignment="Left"</div>
<div>Margin="10,119,0,0"</div>
<div>VerticalAlignment="Top"</div>
<div>Width="460"</div>
<div>ItemsSource="{Binding}"></div>
<div><ListBox.ItemTemplate></div>
<div><DataTemplate></div>
<div><StackPanel></div>
<div><TextBlock Text="{Binding FirstName}" /></div>
<div></StackPanel></div>
<div></DataTemplate></div>
<div></ListBox.ItemTemplate></div>
<div></ListBox></div>
<div>
Now I will create an generic [b]ObservableCollection [/b]object to store the [b]Person [/b]objects.  This will be a class level variable since it will be accessed from multiple events.
</pre>
</div>
<div>public partial class MainPage : PhoneApplicationPage</div>
<div>{</div>
<div>ObservableCollection<Person> personList = new ObservableCollection<Person>();</div>
<div>// Constructor</div>
<div>public MainPage()</div>
<div>{</div>
<div>InitializeComponent();</div>
<div>this.Loaded += new RoutedEventHandler(MainPage_Loaded);</div>
<div>}</div>
<div>void MainPage_Loaded(object sender, RoutedEventArgs e)</div>
<div>{</div>
<div>personList.Add(new Person() { FirstName = "John", LastName = "Doe" });</div>
<div>personList.Add(new Person() { FirstName = "Jane", LastName = "Doe" });</div>
<div>personList.Add(new Person() { FirstName = "John", LastName = "Adams" });</div>
<div>lbNames.ItemsSource = personList;</div>
<div>}</div>
<div>}</div>
<div>
Now I need to create the event handlers for the [b]MouseLeftButtonDown [/b]and [b]MouseLeftButtonUp [/b]events.  This can simply be done by using the [b]Events [/b]list from the [b]Properties [/b]window in the designer.
</pre>
</div>
<div>private void lbNames_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)</div>
<div>{</div>
<div>}</div>
<div>private void lbNames_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)</div>
<div>{</div>
<div>}</div>
<div>
We now need to create two class level objects: a [b]DispatcherTimer [/b]object, and a [b]Person [/b]object.  These are class level because they will need to be accessed from different events.  We will also subscribe to the Tick event for the timer.
</pre>
</div>
<div>ObservableCollection<Person> personList = new ObservableCollection<Person>();</div>
<div>DispatcherTimer timer;</div>
<div>Person selectedPerson = null;</div>
<div>// Constructor</div>
<div>public MainPage()</div>
<div>{</div>
<div>InitializeComponent();</div>
<div>this.Loaded += new RoutedEventHandler(MainPage_Loaded);</div>
<div>timer = new DispatcherTimer();</div>
<div>timer.Tick += delegate(object s, EventArgs e)</div>
<div>{</div>
<div>};</div>
<div>}</div>
<div>
Next, we will add a [b]Popup [/b]in XAML.  This can go above or below the [b]ListBox[/b] that is currently holding the names.
</pre>
</div>
<div><Popup</div>
<div>x:Name="DeleteContextMenu"</div>
<div>Height="200"</div>
<div>Width="400"></div>
<div><!-- This is a ListBox as an ItemTemplate for the Popup --></div>
<div><ListBox</div>
<div>x:Name="lbDeleteContextMenu"</div>
<div>Background="White"</div>
<div>SelectionChanged="DeleteContextMenu_SelectionChanged"></div>
<div><ListBoxItem</div>
<div>Content="Delete Person"</div>
<div>Foreground="Red"</div>
<div>FontSize="25"</div>
<div>FontWeight="Bold"/></div>
<div></ListBox></div>
<div></Popup></div>
<div>
And the event handler for selecting the Delete item…
</pre>
</div>
<div>private void DeleteContextMenu_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)</div>
<div>{</div>
<div>}</div>
<div>
Here is how it’s going to work.  When the user presses down, we will start the timer.  When the user releases, then we stop the timer.  So if the timer’s interval is reached, we know that the user was holding down on the screen, so we will display the popup.
So now we move to our code.  First we are going to handle the [b]MouseLeftButtonDown [/b]event.
</pre>
</div>
<div>private void lbNames_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)</div>
<div>{</div>
<div>// if there is no person selected, then there is no person to delete</div>
<div>//   no need to do any code if nothing is selected</div>
<div>if (selectedPerson == null)</div>
<div>return;</div>
<div>// gets the position of the mouse cursor to set the Margin</div>
<div>//    of the Popup to show at the mouse coordinates.  You</div>
<div>//    may need to tweak these values to get it to display in</div>
<div>//    the correct location.</div>
<div>Point position = e.GetPosition((UIElement)this);</div>
<div>DeleteContextMenu.Margin = new Thickness(position.X, position.Y - 200, 20, 0);</div>
<div>// sets the interval to 1.1 seconds.  This means the user will need</div>
<div>//    to hold down on the screen for 1.1 seconds before we determine</div>
<div>//    to show the ContextMenu.</div>
<div>timer.Interval = TimeSpan.FromMilliseconds(1100);</div>
<div>timer.Start();</div>
<div>}</div>
<div>
Next, we will do our code for the [b]MouseLeftButtonUp[/b] event
</pre>
</div>
<div>private void lbNames_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)</div>
<div>{</div>
<div>// stop the timer when the user releases the screen</div>
<div>timer.Stop();</div>
<div>// sets the class level variable to the selected row</div>
<div>selectedPerson = lbNames.SelectedItem as Person;</div>
<div>}</div>
<div>
Now for our code in the [b]Tick [/b]event for the [b]Timer[/b].
</pre>
</div>
<div>// Constructor</div>
<div>public MainPage()</div>
<div>{</div>
<div>InitializeComponent();</div>
<div>this.Loaded += new RoutedEventHandler(MainPage_Loaded);</div>
<div>timer = new DispatcherTimer();</div>
<div>timer.Tick += delegate(object s, EventArgs e)</div>
<div>{</div>
<div>// stop the timer so that it doesn't popup the Context menu again</div>
<div>timer.Stop();</div>
<div>// since we are using the same ListBox over and over, this will</div>
<div>//   make it so when the Context Menu is shown, there will be no</div>
<div>//   selected item from any previous showing of the Context Menu</div>
<div>lbDeleteContextMenu.SelectedIndex = -1;</div>
<div>// opens the Context Menu</div>
<div>DeleteContextMenu.IsOpen = true;</div>
<div>};</div>
<div>}</div>
<div>
Last, we have our code from the [b]SelectionChanged [/b]event for the [b]ListBox [/b]that is part of the Context Menu.
</pre>
</div>
<div>private void DeleteContextMenu_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)</div>
<div>{</div>
<div>// in the Timer's Tick event, we set the SelectedIndex of the</div>
<div>//   Context Menu's Listbox back to -1.  However, this does</div>
<div>//   fire the SelectionChanged event.  This code will handle that.</div>
<div>if (lbDeleteContextMenu.SelectedIndex == -1)</div>
<div>return;</div>
<div>// closes the Context Menu</div>
<div>DeleteContextMenu.IsOpen = false;</div>
<div>if (selectedPerson == null)</div>
<div>return;</div>
<div>// removes the selected person from the list</div>
<div>personList.Remove(selectedPerson);</div>
<div>// since we are using an ObservableCollection, we do not have</div>
<div>//   to rebind the list to the ListBox.</div>
<div>selectedPerson = null;</div>
<div>}</div>
<div>
Now you can run the application, and you will see the list show up.  You must click on an item first before clicking and holding to show the Context Menu.

In writing one of my Windows Phone 7 applications, I needed to do a allow the user to delete an entry from a ListBox.  Since my ListBox didn’t have enough room for an actual delete button, I decided I would use a ContextMenu to do it.  To my surprise, even though the OS seems to support a long press action(the way to uninstall an application), that action doesn’t seem to be available to developers(or not that I could find).

So I decided to roll my own using the [b]MouseLeftButtonDown [/b]and [b]MouseLeftButtonUp [/b]events, and a [b]DispatcherTimer[/b].
Add these two using statements to the top of the code…
</pre>
</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">using System.Collections.ObjectModel;</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">using System.Windows.Threading;</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">
So first, we need our initial code to get the [b]ListBox [/b]populated.  I created a [b]Person [/b]class just for simplistic reasons.
</pre>
</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">public class Person</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">{</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">public string FirstName { get; set; }</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">public string LastName { get; set; }</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">}</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">
Next, I will set up the [b]ListBox [/b]to simply show the [b]FirstName [/b]of the [b]Person[/b].
</pre>
</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><ListBox</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">Name="lbNames"</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">Height="240"</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">HorizontalAlignment="Left"</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">Margin="10,119,0,0"</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">VerticalAlignment="Top"</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">Width="460"</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">ItemsSource="{Binding}"></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><ListBox.ItemTemplate></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><DataTemplate></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><StackPanel></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><TextBlock Text="{Binding FirstName}" /></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"></StackPanel></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"></DataTemplate></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"></ListBox.ItemTemplate></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"></ListBox></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">
Now I will create an generic [b]ObservableCollection [/b]object to store the [b]Person [/b]objects.  This will be a class level variable since it will be accessed from multiple events.
</pre>
</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">public partial class MainPage : PhoneApplicationPage</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">{</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">ObservableCollection<Person> personList = new ObservableCollection<Person>();</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">// Constructor</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">public MainPage()</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">{</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">InitializeComponent();</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">this.Loaded += new RoutedEventHandler(MainPage_Loaded);</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">}</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">void MainPage_Loaded(object sender, RoutedEventArgs e)</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">{</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">personList.Add(new Person() { FirstName = "John", LastName = "Doe" });</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">personList.Add(new Person() { FirstName = "Jane", LastName = "Doe" });</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">personList.Add(new Person() { FirstName = "John", LastName = "Adams" });</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">lbNames.ItemsSource = personList;</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">}</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">}</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">
Now I need to create the event handlers for the [b]MouseLeftButtonDown [/b]and [b]MouseLeftButtonUp [/b]events.  This can simply be done by using the [b]Events [/b]list from the [b]Properties [/b]window in the designer.
</pre>
</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">private void lbNames_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">{</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">}</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">private void lbNames_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">{</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">}</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">
We now need to create two class level objects: a [b]DispatcherTimer [/b]object, and a [b]Person [/b]object.  These are class level because they will need to be accessed from different events.  We will also subscribe to the Tick event for the timer.
</pre>
</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">ObservableCollection<Person> personList = new ObservableCollection<Person>();</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">DispatcherTimer timer;</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">Person selectedPerson = null;</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">// Constructor</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">public MainPage()</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">{</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">InitializeComponent();</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">this.Loaded += new RoutedEventHandler(MainPage_Loaded);</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">timer = new DispatcherTimer();</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">timer.Tick += delegate(object s, EventArgs e)</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">{</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">};</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">}</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">
Next, we will add a [b]Popup [/b]in XAML.  This can go above or below the [b]ListBox[/b] that is currently holding the names.
</pre>
</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><Popup</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">x:Name="DeleteContextMenu"</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">Height="200"</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">Width="400"></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><!-- This is a ListBox as an ItemTemplate for the Popup --></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><ListBox</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">x:Name="lbDeleteContextMenu"</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">Background="White"</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">SelectionChanged="DeleteContextMenu_SelectionChanged"></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><ListBoxItem</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">Content="Delete Person"</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">Foreground="Red"</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">FontSize="25"</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">FontWeight="Bold"/></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"></ListBox></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"></Popup></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">
And the event handler for selecting the Delete item…
</pre>
</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">private void DeleteContextMenu_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">{</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">}</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">
Here is how it’s going to work.  When the user presses down, we will start the timer.  When the user releases, then we stop the timer.  So if the timer’s interval is reached, we know that the user was holding down on the screen, so we will display the popup.
So now we move to our code.  First we are going to handle the [b]MouseLeftButtonDown [/b]event.
</pre>
</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">private void lbNames_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">{</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">// if there is no person selected, then there is no person to delete</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">//   no need to do any code if nothing is selected</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">if (selectedPerson == null)</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">return;</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">// gets the position of the mouse cursor to set the Margin</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">//    of the Popup to show at the mouse coordinates.  You</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">//    may need to tweak these values to get it to display in</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">//    the correct location.</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">Point position = e.GetPosition((UIElement)this);</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">DeleteContextMenu.Margin = new Thickness(position.X, position.Y - 200, 20, 0);</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">// sets the interval to 1.1 seconds.  This means the user will need</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">//    to hold down on the screen for 1.1 seconds before we determine</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">//    to show the ContextMenu.</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">timer.Interval = TimeSpan.FromMilliseconds(1100);</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">timer.Start();</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">}</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">
Next, we will do our code for the [b]MouseLeftButtonUp[/b] event
</pre>
</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">private void lbNames_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">{</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">// stop the timer when the user releases the screen</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">timer.Stop();</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">// sets the class level variable to the selected row</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">selectedPerson = lbNames.SelectedItem as Person;</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">}</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">
Now for our code in the [b]Tick [/b]event for the [b]Timer[/b].
</pre>
</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">// Constructor</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">public MainPage()</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">{</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">InitializeComponent();</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">this.Loaded += new RoutedEventHandler(MainPage_Loaded);</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">timer = new DispatcherTimer();</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">timer.Tick += delegate(object s, EventArgs e)</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">{</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">// stop the timer so that it doesn't popup the Context menu again</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">timer.Stop();</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">// since we are using the same ListBox over and over, this will</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">//   make it so when the Context Menu is shown, there will be no</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">//   selected item from any previous showing of the Context Menu</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">lbDeleteContextMenu.SelectedIndex = -1;</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">// opens the Context Menu</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">DeleteContextMenu.IsOpen = true;</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">};</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">}</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">
Last, we have our code from the [b]SelectionChanged [/b]event for the [b]ListBox [/b]that is part of the Context Menu.
</pre>
</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">private void DeleteContextMenu_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">{</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">// in the Timer's Tick event, we set the SelectedIndex of the</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">//   Context Menu's Listbox back to -1.  However, this does</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">//   fire the SelectionChanged event.  This code will handle that.</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">if (lbDeleteContextMenu.SelectedIndex == -1)</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">return;</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">// closes the Context Menu</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">DeleteContextMenu.IsOpen = false;</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">if (selectedPerson == null)</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">return;</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">// removes the selected person from the list</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">personList.Remove(selectedPerson);</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">// since we are using an ObservableCollection, we do not have</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">//   to rebind the list to the ListBox.</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">selectedPerson = null;</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">}</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">
Now you can run the application, and you will see the list show up.  You must click on an item first before clicking and holding to show the Context Menu.

In writing one of my Windows Phone 7 applications, I needed to do a allow the user to delete an entry from a ListBox.  Since my ListBox didn’t have enough room for an actual delete button, I decided I would use a ContextMenu to do it.

To my surprise, even though the OS seems to support a long press action(the way to uninstall an application), that action doesn’t seem to be available to developers(or not that I could find).

So I decided to roll my own using the MouseLeftButtonDown and MouseLeftButtonUp events, and a DispatcherTimer.
Add these two using statements to the top of the code…
using System.Collections.ObjectModel;
using System.Windows.Threading;

So first, we need our initial code to get the ListBox populated.  I created a Person class just for simplistic reasons.

public class Person
{
     public string FirstName { get; set; }
     public string LastName { get; set; }
}

Next, I will set up the ListBox to simply show the FirstName of the Person.

<ListBox
     Name="lbNames"
     Height="240"
     HorizontalAlignment="Left"
     Margin="10,119,0,0"
     VerticalAlignment="Top"
     Width="460"
     ItemsSource="{Binding}">

     <ListBox.ItemTemplate>
          <DataTemplate>
               <StackPanel>
                    <TextBlock Text="{Binding FirstName}" />
               </StackPanel>
          </DataTemplate>
     </ListBox.ItemTemplate>
</ListBox>

Now I will create an generic ObservableCollection object to store the Person objects.  This will be a class level variable since it will be accessed from multiple events.

public partial class MainPage : PhoneApplicationPage
{
    ObservableCollection<Person> personList = new ObservableCollection<Person>();

    // Constructor
    public MainPage()
    {
        InitializeComponent();

        this.Loaded += new RoutedEventHandler(MainPage_Loaded);
    }

    void MainPage_Loaded(object sender, RoutedEventArgs e)
    {
        personList.Add(new Person() { FirstName = "John", LastName = "Doe" });
        personList.Add(new Person() { FirstName = "Jane", LastName = "Doe" });
        personList.Add(new Person() { FirstName = "John", LastName = "Adams" });

        lbNames.ItemsSource = personList;
    }
}

Now I need to create the event handlers for the MouseLeftButtonDown and MouseLeftButtonUp events.  This can simply be done by using the Events list from the Properties window in the designer.

private void lbNames_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{

}

private void lbNames_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{

}

We now need to create two class level objects: a DispatcherTimer object, and a Person object.  These are class level because they will need to be accessed from different events.  We will also subscribe to the Tick event for the timer.

ObservableCollection<Person> personList = new ObservableCollection<Person>();

DispatcherTimer timer;

Person selectedPerson = null;

// Constructor
public MainPage()
{
    InitializeComponent();

    this.Loaded += new RoutedEventHandler(MainPage_Loaded);

    timer = new DispatcherTimer();
    timer.Tick += delegate(object s, EventArgs e)
    {

    };
}

Next, we will add a Popup in XAML.  This can go above or below the ListBox that is currently holding the names.

<Popup
    x:Name="DeleteContextMenu"
    Height="200"
    Width="400">

    <!-- This is a ListBox as an ItemTemplate for the Popup -->
    <ListBox
        x:Name="lbDeleteContextMenu"
        Background="White"
        Selectionchanged="DeleteContextMenu_Selectionchanged">

        <ListBoxItem
            Content="Delete Person"
            Foreground="Red"
            FontSize="25"
            FontWeight="Bold"/>

    </ListBox>

</Popup>

And the event handler for selecting the Delete item…

private void DeleteContextMenu_Selectionchanged(object sender, System.Windows.Controls.SelectionchangedEventArgs e)
{

}

Here is how it’s going to work.  When the user presses down, we will start the timer.  When the user releases, then we stop the timer.  So if the timer’s interval is reached, we know that the user was holding down on the screen, so we will display the popup.

So now we move to our code.  First we are going to handle the MouseLeftButtonDown event.

private void lbNames_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
    // if there is no person selected, then there is no person to delete
    //   no need to do any code if nothing is selected
    if (selectedPerson == null)
        return;

    // gets the position of the mouse cursor to set the Margin
    //    of the Popup to show at the mouse coordinates.  You
    //    may need to tweak these values to get it to display in
    //    the correct location.
    Point position = e.GetPosition((UIElement)this);
    DeleteContextMenu.Margin = new Thickness(position.X, position.Y - 200, 20, 0);

    // sets the interval to 1.1 seconds.  This means the user will need
    //    to hold down on the screen for 1.1 seconds before we determine
    //    to show the ContextMenu.
    timer.Interval = TimeSpan.FromMilliseconds(1100);
    timer.Start();
}

Next, we will do our code for the MouseLeftButtonUp event

private void lbNames_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
    // stop the timer when the user releases the screen
    timer.Stop();

    // sets the class level variable to the selected row
    selectedPerson = lbNames.SelectedItem as Person;
}

Now for our code in the Tick event for the Timer.

// Constructor
public MainPage()
{
    InitializeComponent();

    this.Loaded += new RoutedEventHandler(MainPage_Loaded);

    timer = new DispatcherTimer();
    timer.Tick += delegate(object s, EventArgs e)
    {
        // stop the timer so that it doesn't popup the Context menu again
        timer.Stop();

        // since we are using the same ListBox over and over, this will
        //   make it so when the Context Menu is shown, there will be no
        //   selected item from any previous showing of the Context Menu
        lbDeleteContextMenu.SelectedIndex = -1;

        // opens the Context Menu
        DeleteContextMenu.IsOpen = true;
    };
}

Last, we have our code from the SelectionChanged event for the ListBox that is part of the Context Menu.

private void DeleteContextMenu_Selectionchanged(object sender, System.Windows.Controls.SelectionchangedEventArgs e)
{
    // in the Timer's Tick event, we set the SelectedIndex of the
    //   Context Menu's Listbox back to -1.  However, this does
    //   fire the Selectionchanged event.  This code will handle that.
    if (lbDeleteContextMenu.SelectedIndex == -1)
        return;

    // closes the Context Menu
    DeleteContextMenu.IsOpen = false;

    if (selectedPerson == null)
        return;

    // removes the selected person from the list
    personList.Remove(selectedPerson);

    // since we are using an ObservableCollection, we do not have
    //   to rebind the list to the ListBox.

    selectedPerson = null;
}

Now you can run the application, and you will see the list show up.  You must click on an item first before clicking and holding to show the Context Menu.

Tags: , , , ,