Eclipsed4utoo's Blog
Not Your Ordinary Programmer

Posts Tagged ‘Silverlight’

WP7 – Context Menu From Listbox

Thu ,26/08/2010
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.

Silverlight 4 – Creating a Custom Modal Dialog

Fri ,23/07/2010

For a Silverlight application I did recently, I wanted to do a custom modal dialog box for showing informational messages, error messages, or other messages to the user.  This dialog box would have no title bar or “X” button, and would have rounded corners.

For this tutorial, we will use Blend 4 to accomplish our task.

First, create a new Silverlight 4 application.  I named mine CustomDialog.

Image1

Once the project has been created, we are going to add a new item to our Silverlight project.  This item will be a ChildWindow.  I named mine DialogPopup.

Image2

The ChildWindow will handle the modal dialog part of our window.  However, there are parts of the ChildWindow that I didn’t like and wanted to remove/change, such as the window chrome.  I also wanted to round the corners of the window.   To do this, we need to edit the template for the window.  In the Objects and Timeline window, right-click on the ChildWindow parent –> Edit Template –> Edit a Copy

Image3

We are going to keep it simple and save the new style to the ChildWindow document.

Image4

So first, we are just going to delete the window chrome from the window.  The window chrome is the title bar and the “X” used to close the window.  Drill-down in the treeview until you find the Chrome entry.  Right-click, and choose Delete.

Image5

Next, we need to delete some of the Borders.  These give the window a grey border that I didn’t want.

Image11

Next, we are going to round the corners of the window.  Drill-down and click on the Border shown below.

Image12

In the Properties window, set the CornerRadius to 20.

Image7

Move down to the next Border,

Image13

And set it’s CornerRadius to 20.

Image9

With the same Border selected, in the Properties window, set the Background Brush to a color of your choice.

Image10

The window “jazz” is now complete.  Next, we are going to move to the XAML.

First, we need to give our window a name so we can handle binding.  I named mine myCustomPopup.

<sdk:ChildWindow
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
   x:Class="CustomDialog.DialogPopup"
   x:Name="myCustomPopup"
   Title="DialogPopup"
   Width="400" Height="300">

Now we need to add a TextBlock to the window to hold our message.

<TextBlock
    Text="{Binding Message, ElementName=myCustomPopup}"
    Margin="51,88,57,113"
    TextWrapping="Wrap"
    Foreground="#FF1D1515"
    FontWeight="Bold"
    TextAlignment="Center"/>

You may notice that we are binding to a property called Message.  This is a custom DependencyProperty that will correspond to a public property that we will set when we create an instance of the window.

/// <summary>
/// Creates a public property for the TextBlock to bind to
/// </summary>
public static DependencyProperty MessageProperty = DependencyProperty.Register("Message", typeof(string), typeof(DialogPopup), new PropertyMetadata(""));
public string Message
{
     get { return (string)GetValue(MessageProperty); }
     set { SetValue(MessageProperty, value); }
}

This will complete our work for the window.  To show off the new window, lets add a Button to the MainPage.xaml, create an EventHandler for the Click event.

<Grid
   x:Name="LayoutRoot"
   Background="White">

     <Button
        x:Name="btnShowMessage"
        Content="Click Me"
        Click="btnShowMessage_Click"
        Margin="251,207,289,236"  />
</Grid>

And the code for the Click event…

private void btnShowMessage_Click(object sender, System.Windows.RoutedEventArgs e)
{
     DialogPopup dialog = new DialogPopup();
     dialog.Message = "Our message";
     dialog.Show();
}

And that will complete our tutorial.  Run the application from Blend using F5, and you should see this..

Image14

Silverlight 4 – Publishing Application to Remote Server

Thu ,22/07/2010

This blog post will talk about the steps needed to publish a Silverlight 4 applications that uses WCF RIA Services for communication.  There were a number of issues that I ran into trying to publish, so I decided to do a blog post to keep other’s from having to search and hunt for the fixes.

NOTE:  These steps are for IIS running on Windows Server 2003 SP2.  Steps may be different for other versions of IIS.

1.  First, you will need to fix your web.config file as I have noted in this blog post.  This is not added by default.

2. (Optional) If you are running a .Net 2.0 or .Net 3.5 website on this same server, you will need to create a new AppPool in IIS.  This is required because an AppPool can only run one version of the .Net CLR.  With .Net 4, Microsoft created a new CLR.  Therefore, you will need an AppPool for the .Net 2.0 and .Net 3.5 websites, and an AppPool for the .Net 4 websites.  NOTE:  This may have changed in later versions of IIS.

3.  Next, in Visual Studio 2010, you will need to set a number of the references of the .Web project to Copy to Local.  I had to do it for all of the System.ServiceModel references.  You may not have all of these references, and that is fine.

SLImage4

Then go to the Properties window, and set Copy Local equal to True.

SLImage5

4.  Next, you need to add a new MIME type for both the .XAP extension and the .XAML extension.

Open the IIS Management console.  Drill-down until you get to your domain/default website.  Right-click and click Properties.
SLImage1

Next, go to the HTTP Headers tab, then click on the Mime Types… button.
SLImage2

Now add the two new mime types..
SLImage3

Now simply publish your web project to your server, and you should be ready to go.

NOTE: This blog post does not talk about creating a Virtual Directory or making the Virtual Directory an application.  There are plenty of other blog posts that can walk you through that.  However, make sure the Virtual Directory is set to the AppPool for .Net 4(if it was required for your setup).