.NET Zone is brought to you in partnership with:

My name is Nico, I’m an MCP living in Belgium. I’m currently employed as a .net developer at RealDolmen, one of Belgium’s leading IT single source providers. In my spare team I'm usually playing around with the Windows Phone and Windows 8 SDK, trying out cool stuff and blogging about it. I'm also founding member and board member of the Belgian Metro App Developer Network, a user group focussed on Windows 8 and Windows Phone and a Dzone MVB Nico is a DZone MVB and is not an employee of DZone and has posted 9 posts at DZone. You can read more from them at their website. View Full User Profile

LLS SelectedItem Binding Through a Behavior

01.14.2014
| 2636 views |
  • submit to reddit

Back in August I blogged about the ExtendedSelector, an extension of the LongListSelector that gave us a bindable SelectedItem property. A bit of a downside of this approach is that it’s basically a new control. Sure it inherits from the classic LLS underneath but it’s still another control in your XAML code.

Well, to fix this I’ve recreated the SelectedItem dependency property  through a behavior.

The behavior

public class SelectedItemBehavior : Behavior<LongListSelector>
{
    public readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register(
        "SelectedItem", typeof(object), typeof(SelectedItemBehavior), new PropertyMetadata(default(object)));
 
    public object SelectedItem
    {
        get { return GetValue(SelectedItemProperty); }
        set { SetValue(SelectedItemProperty, value); }
    }
 
    protected override void OnAttached()
    {
        AssociatedObject.SelectionChanged += AssociatedObjectOnSelectionChanged;
 
        base.OnAttached();
    }
 
    protected override void OnDetaching()
    {
        AssociatedObject.SelectionChanged -= AssociatedObjectOnSelectionChanged;
 
        base.OnDetaching();
    }
 
    private void AssociatedObjectOnSelectionChanged(object sender, SelectionChangedEventArgs args)
    {
        SelectedItem = args.AddedItems[0];
    }
}

It’s an easy one really. The behavior inherits from Behavior<LongListSelector> and has one dependency property. When the behavior gets attached to an LLS we attach the event handler to the SelectionChanged event. When detaching we cleanup by detaching the event handler.

When the SelectionChanged event fires we push the selected item into the dependency property.

Usage

Let’s throw together a quick little app to show the usage of the behavior. First the infamous Person class

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

Next is the MainViewModel

public class MainViewModel : INotifyPropertyChanged
{
    private ObservableCollection<Person> _persons;
    private Person _selectedPerson;
 
    public ObservableCollection<Person> Persons
    {
        get { return _persons; }
        set
        {
            if (_persons == value) return;
 
            _persons = value;
 
            OnPropertyChanged();
        }
    }
 
    public Person SelectedPerson
    {
        get { return _selectedPerson; }
        set
        {
            if (_selectedPerson == value) return;
 
            _selectedPerson = value;
 
            OnPropertyChanged();
        }
    }
 
    public MainViewModel()
    {
        Persons = new ObservableCollection<Person>();
        Random rnd = new Random();
 
        for (int i = 0; i < 20; i++)
        {
            var person = new Person {Name = "Person " + i, Age = rnd.Next(0, 80)};
 
            Persons.Add(person);
        }
    }
 
    public event PropertyChangedEventHandler PropertyChanged;
 
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

Two properties here, an observable collection that holds the persons and a SelectedPerson that will be bound to the dependency property on our behavior. The list of persons gets filled with some random data from the constructor.

Here’s the view

<Grid x:Name="LayoutRoot" Background="Transparent">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
 
    <!--  TitlePanel contains the name of the application and page title  -->
    <StackPanel x:Name="TitlePanel"
        Grid.Row="0"
        Margin="12,17,0,28">
        <TextBlock Margin="12,0"
            Style="{StaticResource PhoneTextNormalStyle}"
            Text="MY APPLICATION" />
        <TextBlock Margin="9,-7,0,0"
            Style="{StaticResource PhoneTextTitle1Style}"
            Text="page name" />
    </StackPanel>
 
    <!--  ContentPanel - place additional content here  -->
    <Grid x:Name="ContentPanel"
        Grid.Row="1"
        Margin="12,0,12,0">
 
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <TextBlock Grid.Row="0">
            <Run Text="Selected person is " />
            <Run Text="{Binding SelectedPerson.Age}" />
            <Run Text=" years old" />
        </TextBlock>
        <phone:LongListSelector Grid.Row="1"
            ItemsSource="{Binding Persons}">
            <phone:LongListSelector.ItemTemplate>
                <DataTemplate>
                    <Grid Margin="0, 12, 0, 0">
                        <TextBlock Text="{Binding Name}" />
                    </Grid>
                </DataTemplate>
            </phone:LongListSelector.ItemTemplate>
            <i:Interaction.Behaviors>
                <vm:SelectedItemBehavior SelectedItem="{Binding SelectedPerson, Mode=TwoWay}"/>
            </i:Interaction.Behaviors>
        </phone:LongListSelector>
    </Grid>
</Grid>

Let’s extract the LongListSelector from that page as that’s the important piece

<phone:LongListSelector Grid.Row="1"
    ItemsSource="{Binding Persons}">
    <phone:LongListSelector.ItemTemplate>
        <DataTemplate>
            <Grid Margin="0, 12, 0, 0">
                <TextBlock Text="{Binding Name}" />
            </Grid>
        </DataTemplate>
    </phone:LongListSelector.ItemTemplate>
    <i:Interaction.Behaviors>
        <vm:SelectedItemBehavior SelectedItem="{Binding SelectedPerson, Mode=TwoWay}"/>
    </i:Interaction.Behaviors>
</phone:LongListSelector>

The ItemsSource is bound to the Persons ObservableCollection on the viewmodel. Underneath the ItemTemplate we attach the behavior and bind its property to the SelectedItem.

And that’s it, every time a person is selected from the LLS the SelectedPerson property gets updated on the viewmodel.

Published at DZone with permission of Nico Vermeir, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)