Click here to Skip to main content
Click here to Skip to main content

A Simple WP7 JumpList in WPF

By , 22 May 2011
 

Introduction

I am deeply impressed by Metro UI, the typography based design created by Microsoft. It is very clean and fast. In this article, I am demonstrating a simple example of how a WP7 JumpList can be created in WPF. The WP7 JumpList was demonstrated in the MIX '11 event.

WP7 JumpList Image

Using the Code

The WPF JumpList control is composed of two controls:

  • IndexControl - used to display the indices.
  • JumpListControl - encapsulates the contents of the JumpList.

IndexControl

The IndexControl is used to display the index in the ValuesPanel as well as the JumpListPanel. It has a dependency property IndexValue which is used to display the index value in the IndexControl.

public static readonly DependencyProperty IndexValueProperty =
    DependencyProperty.Register("IndexValue", typeof(string), typeof(IndexControl),
        new FrameworkPropertyMetadata
        ((new PropertyChangedCallback(OnIndexValueChanged))));

The IndexControl also has a dependency property IndexState to define its state.

public static readonly DependencyProperty IndexStateProperty =
    DependencyProperty.Register("IndexState", 
    typeof(IndexStateType), typeof(IndexControl),
    new FrameworkPropertyMetadata(IndexStateType.ListDisplay, 
    (new PropertyChangedCallback(OnIndexStateChanged))));

There are three states, defined by the enum IndexStateType.

public enum IndexStateType
{
    // The state when the IndexControl is displayed in the long list.
    ListDisplay,
    // The state when the IndexControl is displayed in the JumpList 
    // and this index has NO values
    IndexNotFound,
    // The state when the IndexControl is displayed in the JumpList 
    // and this index has values
    IndexFound
}

Based on its state, the look and feel of the IndexControl changes.

IndexState Types

JumpListControl

The WPF JumpList control has two panels:

  • ValuesPanel - used to display the values (names) in a long list format.
  • JumpListPanel - used to display the indices.

At any given instance, only one of the above panels is visible in the JumpListControl, while the other panel remains hidden.

ValuesPanel

WPF JumpList Image

The ValuesPanel displays the values (or names) in a long list format. For each index, the IndexControl and the set of Names are encapsulated in a StackPanel and added to the parent StackPanel.

Values Panel Image

JumpListPanel

WPF JumpList Image

The JumpListPanel consists of a WrapPanel in which the IndexControls are added.

JumpList Panel Image

The JumpListPanel defines two dependency properties:

  • Values - ObservableCollection<string> - serves as an input for the control.
    public static readonly DependencyProperty ValuesProperty =
        DependencyProperty.Register("Values", 
        typeof(ObservableCollection<string>), typeof(JumpListControl),
        new FrameworkPropertyMetadata
        ((new PropertyChangedCallback(OnValuesChanged))));
  • SelectedValue - indicates the value (or Name) selected by the user.
    public static readonly DependencyProperty SelectedValueProperty =
        DependencyProperty.Register("SelectedValue", 
        typeof(string), typeof(JumpListControl),
        new FrameworkPropertyMetadata
        ((new PropertyChangedCallback(OnSelectedValueChanged))));

When the JumpListControl is initialized, it adds IndexControls, to the JumpListPanel, for the indices a-z. The state of each of the IndexControls is set to IndexNotFound.

public JumpListControl()
{
    InitializeComponent();

    JumpListScrollView.Visibility = System.Windows.Visibility.Hidden;

    foreach (char idx in indexes)
    {
        IndexControl idxCtrl = new IndexControl
        {
            Width = 50,
            Height = 50,
            IndexValue = idx.ToString(),
            IndexState = IndexStateType.IndexNotFound,
            Margin = new Thickness(4, 4, 0, 0)
        };

        idxCtrl.MouseLeftButtonDown += 
            new MouseButtonEventHandler(OnIndexClickedInJumpList);

        JumpListPanel.Children.Add(idxCtrl);
    }
}

When the Values dependency property is set by the user, the JumpListControl parses the list and creates the indexed long list in the ValuesPanel and changes the state of the IndexControls, in the JumpListPanel, from IndexNotFound to IndexFound.

private void Parse(ObservableCollection<string> values)
{
    Dictionary<string, List<string>> valueDict = new Dictionary<string, List<string>>();

    List<string> valueList = values.ToList();

    // Sort the values
    valueList.Sort();

    // Get the distinct indexes
    foreach (string str in valueList)
    {
        string key = Char.ToLower(str[0]).ToString();
        if (!valueDict.ContainsKey(key))
        {
            valueDict[key] = new List<string>();
        }
        valueDict[key].Add(str);
    }

    // Set the IndexState of all the IndexControls 
    // whose index has been found as IndexFound
    JumpListPanel.Children.OfType<IndexControl>()
                          .Where(i => valueDict.Keys.Contains(i.IndexValue))
                          .All(i =>
                          {
                              i.IndexState = IndexStateType.IndexFound;
                              return true;
                          });


    // Add the index and the related names to the Values Panel
    foreach (string key in valueDict.Keys)
    {
        StackPanel stkPanel = new StackPanel 
	{ HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch };

        IndexControl idxCtrl = new IndexControl
        {
            Width = 50,
            Height = 50,
            IndexValue = key,
            IndexState = IndexStateType.ListDisplay,
            Margin = new Thickness(4),
            HorizontalAlignment = System.Windows.HorizontalAlignment.Left,
            VerticalAlignment = System.Windows.VerticalAlignment.Center
        };

        idxCtrl.MouseLeftButtonDown += 
		new MouseButtonEventHandler(OnIndexClickedInValuesPanel);

        stkPanel.Children.Add(idxCtrl);

        foreach (string str in valueDict[key])
        {
            TextBlock tb = new TextBlock
            {
                FontFamily = font,
                FontWeight = FontWeights.Light,
                FontSize = 22,
                Foreground = Brushes.White,
                TextAlignment = TextAlignment.Left,
                Margin = new Thickness(4, 4, 0, 0),
                Text = str,
                HorizontalAlignment = System.Windows.HorizontalAlignment.Left,
                VerticalAlignment = System.Windows.VerticalAlignment.Center
            };

            tb.MouseLeftButtonDown += new MouseButtonEventHandler(OnValueSelected);

            stkPanel.Children.Add(tb);
        }

        ValuesPanel.Children.Add(stkPanel);
    }
}

When the ValuesPanel is being displayed and the user clicks on any of the indices, then the ValuesPanel is hidden and the JumpListPanel is displayed. When the user clicks on any of the indices in the JumpListPanel, the JumpListPanel is hidden, the ValuesPanel is displayed and the ValuePanel scrolls to the index selected by the user.

Clicking on any of the Names will set the SelectedValue property of the JumpListControl.

EndPoint

What I have attempted here is a basic implementation of the JumpList control which accepts a list of strings as input. It can be further modified to accept a collection of objects (say a person's record) and an image can be displayed alongside each name in the ValuesPanel.

Points of Interest

An important lesson I learnt during the development of this control is that when you are adding items to a WrapPanel (say with Orientation=Horizontal) and the items extend beyond the height of the WrapPanel, then the vertical scrollbar will not appear automatically (even though you set ScrollViewer.VerticalScrollBarVisibility="Auto").

To overcome this problem, you need to wrap your WrapPanel with a ScrollViewer.

<ScrollViewer Name="JumpListScrollView"
              HorizontalScrollBarVisibility="Disabled"
              VerticalScrollBarVisibility="Auto">
    <WrapPanel Name="JumpListPanel"
               Orientation="Horizontal">
    </WrapPanel>
</ScrollViewer>

History

  • 22nd May, 2010 - Version 1.0 released

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Ratish Philip
Software Developer
India India
Member
Ratish Philip is a software developer with 8 years of experience. He loves programming in C#, WPF & Silverlight.
 
He is currently exploring the depths of Windows 8 programming.
 
Creating enriched user experiences is what appeals to him the most.
 
Occasionally expresses his creativity through pencil sketching too!
 
Ratish's personal blog: wpfspark.wordpress.com

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionSilverlight version works [modified]memberMember 165621431 Oct '11 - 7:46 
Sorry for the delay...
Just to inform you that I managed to build
a Silverlight version of the WP 7 jumplist...
Starting from the WPF code example and strategy you suggested, I had to make some changes, as some WPF methods and properties aren't supported in Silverlight... at least not yet...
ex: Had to use ScrollIntoView instead of BringIntoView...

I also prefered dealing with Opacity instead of Visibility
and thought of eventually even adding somekind of nice swivel effect transition in between
to jazz it up Smile | :)
Overall it works pretty well and modifying the code to run with datas fed in WCF shouldn't be a problem for me at this stage...
Regards
DC

modified 31 Oct '11 - 17:08.

AnswerRe: Silverlight version worksmemberRatish Philip1 Nov '11 - 1:05 
Great news! Smile | :)
cheers,
Ratish Philip
Blog: http://wpfspark.wordpress.com/

QuestionNice jobmemberMember 165621421 Sep '11 - 10:54 
This is what I call a pretty neat initiative. I know this was done in WPF XAML and haven't tried the code in Silverlight app yet, though I assume I can manage to make it run in Silverlight.
Sure we'll give it a try and see what comes up... Thank's for sharing.
AnswerRe: Nice jobmemberRatish Philip25 Sep '11 - 1:44 
Thanks Member 1656214.
I think this will work in Silverlight too without much changes.
 
Do let me know of the results.
cheers,
Ratish Philip
Blog: http://wpfspark.wordpress.com/

GeneralMy vote of 5memberFilip D'haene26 May '11 - 8:47 
Very nice!
 
Thanks for sharing. Smile | :)
GeneralRe: My vote of 5memberRatish Philip26 May '11 - 15:28 
Thanks Filip.
cheers,
Ratish Philip
Blog: http://wpfspark.wordpress.com/

GeneralNice navigational aidmemberNic_Roche23 May '11 - 13:57 
It works well with ObservableCollection<string>, but most useful data-bound list controls use the ItemSource, DisplayMemberPath, ValueMemberPath pattern.
 
Anyhow, well done; a good starting point.
GeneralRe: Nice navigational aidmemberRatish Philip23 May '11 - 14:34 
Thanks Nic_Roche,
I am working on the next version of the JumpListControl which will focus on real world data.
 
cheers,
Ratish
Ratish Philip

GeneralRe: Nice navigational aidmemberNic_Roche24 May '11 - 11:42 
Hi,
 
Just a quick/incomplete refactor of your code (no redesign):
 
(MainWindow.xaml)
<Window x:Class="JumpList.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="JumpList Sample"
        Height="523"
        Width="444"
        xmlns:my="clr-namespace:JumpList">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <my:JumpListControl 
            Grid.Column="0"
            x:Name="jumpListControl1"
            DisplayMemberPath="DisplayName"
            ValueMemberPath="Value"
            Values="{Binding Values}"/>
        <StackPanel  
            Grid.Column="1">
            <TextBlock
                   Margin="10"
                   Text="{Binding ElementName=jumpListControl1, Path=SelectedValue.Value, StringFormat='Selected Value = {0}', FallbackValue='Nothing Selected!'}"></TextBlock>
            <TextBlock 
                   Margin="10"
                   Text="{Binding ElementName=jumpListControl1, Path=SelectedValue.DisplayName, StringFormat='Selected Text = {0}', FallbackValue='Nothing Selected!'}"></TextBlock>
        </StackPanel>
     </Grid>
</Window>
 

(MainWindow.xaml.cs)
 
using System.Collections.ObjectModel;
using System.Windows;
 
namespace JumpList
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public ObservableCollection<object> Values { get; set; }
 
        public MainWindow()
        {
            InitializeComponent();
 
            InitializeJumpListValues();
            this.DataContext = this;
        }
 
        private void InitializeJumpListValues()
        {
            Values = new ObservableCollection<object>();
            Values.Add(new { Value = 1, DisplayName = "Adams" });
            Values.Add(new { Value = 2, DisplayName = "Adkins"});
            Values.Add(new { Value = 3, DisplayName = "Aguilar"});
            Values.Add(new { Value = 4, DisplayName = "Alexander"});
            Values.Add(new { Value = 5, DisplayName = "Atkins"});
            Values.Add(new { Value = 6, DisplayName = "Austin"});
            Values.Add(new { Value = 7, DisplayName = "Cain"});
            Values.Add(new { Value = 8, DisplayName = "Caldwell"});
            Values.Add(new { Value = 9, DisplayName = "Campbell"});
            Values.Add(new { Value = 10, DisplayName = "Copeland"});
            Values.Add(new { Value = 11, DisplayName = "Cortez"});
            Values.Add(new { Value = 12, DisplayName = "Cox"});
            Values.Add(new { Value = 13, DisplayName = "Craig"});
            Values.Add(new { Value = 14, DisplayName = "Crawford"});
            Values.Add(new { Value = 15, DisplayName = "Cross"});
            Values.Add(new { Value = 16, DisplayName = "Cruz"});
            Values.Add(new { Value = 17, DisplayName = "Cummings"});
            Values.Add(new { Value = 18, DisplayName = "Cunningham"});
            Values.Add(new { Value = 19, DisplayName = "Curry"});
            Values.Add(new { Value = 20, DisplayName = "Curtis"});
            // you get the drift...

        }
    }
}
 
 
(JumpListControl.xaml.cs)
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
 
namespace JumpList
{
    /// <summary>
    /// Interaction logic for JumpListControl.xaml
    /// </summary>
    public partial class JumpListControl : UserControl
    {
        #region Fields
 
        private string indexes = "abcdefghijklmnopqrstuvwxyz";
        private FontFamily font = new FontFamily("Segoe WP");
 
        #endregion
 
        #region Dependency Properties
 

        #region DisplayMemberPath
 
        /// <summary>
        /// DisplayMemberPath Dependency Property
        /// </summary>
        public static readonly DependencyProperty DisplayMemberPathProperty =
            DependencyProperty.Register("DisplayMemberPath", typeof(string), typeof(JumpListControl),
                new FrameworkPropertyMetadata());
 
        /// <summary>
        /// Gets or sets the SelectedValue property. This dependency property 
        /// indicates the selected Value.
        /// </summary>
        public string DisplayMemberPath
        {
            get { return (string)GetValue(DisplayMemberPathProperty); }
            set { SetValue(DisplayMemberPathProperty, value); }
        }
 
        #endregion
 

        #region ValueMemberPath
 
        /// <summary>
        /// DisplayMemberPath Dependency Property
        /// </summary>
        public static readonly DependencyProperty ValueMemberPathProperty =
            DependencyProperty.Register("ValueMemberPath", typeof(string), typeof(JumpListControl),
                new FrameworkPropertyMetadata());
 
        /// <summary>
        /// Gets or sets the SelectedValue property. This dependency property 
        /// indicates the selected Value.
        /// </summary>
        public string ValueMemberPath
        {
            get { return (string)GetValue(ValueMemberPathProperty); }
            set { SetValue(ValueMemberPathProperty, value); }
        }
 
        #endregion
 
        #region SelectedValue
 
        /// <summary>
        /// SelectedValue Dependency Property
        /// </summary>
        public static readonly DependencyProperty SelectedValueProperty =
            DependencyProperty.Register("SelectedValue", typeof(object), typeof(JumpListControl),
                new FrameworkPropertyMetadata((new PropertyChangedCallback(OnSelectedValueChanged))));
 
        /// <summary>
        /// Gets or sets the SelectedValue property. This dependency property 
        /// indicates the selected Value.
        /// </summary>
        public object SelectedValue
        {
            get { return (object)GetValue(SelectedValueProperty); }
            set { SetValue(SelectedValueProperty, value); }
        }
 
        /// <summary>
        /// Handles changes to the SelectedValue property.
        /// </summary>
        /// <param name="d">JumpListControl</param>
        /// <param name="e">DependencyProperty changed event arguments</param>
        private static void OnSelectedValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            JumpListControl jlCtrl = (JumpListControl)d;
            object oldSelectedValue = e.OldValue;
            object newSelectedValue = jlCtrl.SelectedValue;
            jlCtrl.OnSelectedValueChanged(oldSelectedValue, newSelectedValue);
        }
 
        /// <summary>
        /// Provides derived classes an opportunity to handle changes to the SelectedValue property.
        /// </summary>
        /// <param name="oldSelectedValue">Old Value</param>
        /// <param name="newSelectedValue">New Value</param>
        protected virtual void OnSelectedValueChanged(object oldSelectedValue, object newSelectedValue)
        {
 
        }
 
        #endregion
        
        #region Values
 
        /// <summary>
        /// Values Dependency Property
        /// </summary>
        public static readonly DependencyProperty ValuesProperty =
            DependencyProperty.Register("Values", typeof(IEnumerable), typeof(JumpListControl),
                new FrameworkPropertyMetadata((new PropertyChangedCallback(OnValuesChanged))));
 
        /// <summary>
        /// Gets or sets the Values property. This dependency property 
        /// indicates the list of values to be displayed.
        /// </summary>
        public IEnumerable Values
        {
            get { return (IEnumerable)GetValue(ValuesProperty); }
            set { SetValue(ValuesProperty, value); }
        }
 
        /// <summary>
        /// Handles changes to the Values property.
        /// </summary>
        /// <param name="d">JumpListControl</param>
        /// <param name="e">DependencyProperty changed event arguments</param>
        private static void OnValuesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            JumpListControl jlCtrl = (JumpListControl)d;
            IEnumerable oldValues = (IEnumerable)e.OldValue;
            IEnumerable newValues = jlCtrl.Values;
            string displayMemberPath = (string)d.GetValue(DisplayMemberPathProperty);
            string valueMemberPath = (string)d.GetValue(ValueMemberPathProperty);
            jlCtrl.OnValuesChanged(displayMemberPath, valueMemberPath, oldValues, newValues);
        }
 
        /// <summary>
        /// Provides derived classes an opportunity to handle changes to the Values property.
        /// </summary>
        /// <param name="oldValues">Old Value</param>
        /// <param name="newValues">New Value</param>
        protected virtual void OnValuesChanged(string displayMemberPath, string valueMemberPath, IEnumerable oldValues, IEnumerable newValues)
        {
            Parse(displayMemberPath, valueMemberPath, newValues);
        }
 
        #endregion
 
        #endregion
 
        /// <summary>
        /// Ctor
        /// </summary>
        public JumpListControl()
        {
            InitializeComponent();
 
            JumpListScrollView.Visibility = System.Windows.Visibility.Hidden;
 
            foreach (char idx in indexes)
            {
                IndexControl idxCtrl = new IndexControl
                {
                    Width = 50,
                    Height = 50,
                    IndexValue = idx.ToString(),
                    IndexState = IndexStateType.IndexNotFound,
                    Margin = new Thickness(4, 4, 0, 0)
                };
 
                idxCtrl.MouseLeftButtonDown += new MouseButtonEventHandler(OnIndexClickedInJumpList);
 
                JumpListPanel.Children.Add(idxCtrl);
            }
        }
 
        /// <summary>
        /// Creates indexes based on the list of values provided
        /// </summary>
        /// <param name="newValues"></param>
        private void Parse(string displayMemberPath, string valueMemberPath, IEnumerable newValues)
        {
            Dictionary<string, List<object>> valueDict = new Dictionary<string, List<object>>();
 

            //List<string> valueList = (List<string>)newValues;

            // Sort the values
            //valueList.Sort();
 
            // Get the distinct indexes
            foreach (object obj in newValues)
            {
                string displayName = obj.GetStringProperty(displayMemberPath);
                string key = Char.ToLower(displayName[0]).ToString();
                if (!valueDict.ContainsKey(key))
                {
                    valueDict[key] = new List<object>();
                }
                valueDict[key].Add(obj);
            }
 
            // Set the IndexState of all the IndexControls whose index has been found as IndexFound
            JumpListPanel.Children.OfType<IndexControl>()
                                  .Where(i => valueDict.Keys.Contains(i.IndexValue))
                                  .All(i =>
                                  {
                                      i.IndexState = IndexStateType.IndexFound;
                                      return true;
                                  });
 

            // Add the index and the related names to the Values Panel
            foreach (string key in valueDict.Keys)
            {
                StackPanel stkPanel = new StackPanel { HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch };
 
                IndexControl idxCtrl = new IndexControl
                {
                    Width = 50,
                    Height = 50,
                    IndexValue = key,
                    IndexState = IndexStateType.ListDisplay,
                    Margin = new Thickness(4),
                    HorizontalAlignment = System.Windows.HorizontalAlignment.Left,
                    VerticalAlignment = System.Windows.VerticalAlignment.Center
                };
 
                idxCtrl.MouseLeftButtonDown += new MouseButtonEventHandler(OnIndexClickedInValuesPanel);
 
                stkPanel.Children.Add(idxCtrl);
 
                foreach (object obj in valueDict[key])
                {
                    string displayName = obj.GetStringProperty(displayMemberPath);
                    TextBlock tb = new TextBlock
                    {
                        FontFamily = font,
                        FontWeight = FontWeights.Light,
                        FontSize = 22,
                        Foreground = Brushes.White,
                        TextAlignment = TextAlignment.Left,
                        Margin = new Thickness(4, 4, 0, 0),
                        Text = displayName,
                        Tag = obj,
                        HorizontalAlignment = System.Windows.HorizontalAlignment.Left,
                        VerticalAlignment = System.Windows.VerticalAlignment.Center
                    };
 
                    tb.MouseLeftButtonDown += new MouseButtonEventHandler(OnValueSelected);
 
                    stkPanel.Children.Add(tb);
                }
 
                ValuesPanel.Children.Add(stkPanel);
            }
        }
 
        /// <summary>
        /// Handler for the event when the user clicks on any index in the JumpList.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void OnIndexClickedInJumpList(object sender, MouseButtonEventArgs e)
        {
            IndexControl idxCtrl = sender as IndexControl;
 
            if ((idxCtrl != null) && (idxCtrl.IndexState == IndexStateType.IndexFound))
            {
                this.Dispatcher.BeginInvoke(new Action(() =>
                {
                    JumpListScrollView.Visibility = System.Windows.Visibility.Hidden;
                    ValuesScrollView.Visibility = System.Windows.Visibility.Visible;
 
                    StackPanel sp = ValuesPanel.Children.OfType<StackPanel>().Where(s => s.Children.OfType<IndexControl>().First().IndexValue == idxCtrl.IndexValue).FirstOrDefault();
 
                    if (sp != null)
                    {
                        sp.Children.OfType<IndexControl>().First().BringIntoView(new Rect(0, 0, 100, 400));
                    }
                }));
            }
        }
 
        /// <summary>
        /// Handler for the event when the user clicks on the index in the Values Panel
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void OnIndexClickedInValuesPanel(object sender, MouseButtonEventArgs e)
        {
            this.Dispatcher.BeginInvoke(new Action(() =>
            {
                ValuesScrollView.Visibility = System.Windows.Visibility.Hidden;
                JumpListScrollView.Visibility = System.Windows.Visibility.Visible;
            }));
        }
 
        /// <summary>
        /// Handler for the event when the user clicks on a value
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void OnValueSelected(object sender, MouseButtonEventArgs e)
        {
            TextBlock tb = sender as TextBlock;
 
            if (tb != null)
            {
                SelectedValue = tb.Tag;
            }
        }
    }
}
 
 
This does no validation on missing or wrong values, and uses reflection in the parse method.
 
ValueMemberPath is not being used yet. The SelectedItem is being substituted for the SelectedValue.
 
Thought it just makes your great WPF cut-over a bit more use-able.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130523.1 | Last Updated 22 May 2011
Article Copyright 2011 by Ratish Philip
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid