开发者

In Silverlight, how to bind ListBox item selection to a Navigate event?

I am writing a windows-phone 7 applicat开发者_Go百科ion. I've got a page with a list of TextBlock(s) contained in a ListBox. The behavior I want is that upon clicking one of those TextBlock(s) the page is redirected to a different one, passing the Text of that TextBlock as an argument.

This is the xaml code: (here I am binding to a collection of strings, and the event MouseLeftButtonDown is attached to each TextBlock).

<ListBox x:Name="List1" ItemsSource="{Binding}">
    <ListBox.ItemTemplate>
        <DataTemplate>

            <TextBlock MouseLeftButtonDown="List1_MouseLeftButtonDown" Text="{Binding}"
                       FontSize="20"/> 
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

But this has been unsuccessful for me. I have tried attaching MouseLeftButtonDown event to either the individual TextBox(es) or to the ListBox. And I have had exceptions raised as soon as I use NavigationService.Navigate(uri). Which event should be attached? Should the event be attached to the individual items or to the list as a whole?

I have found a way to work around this problem by populating ListBox with HyperlinkButton(s). However, I would like to understand why the TextBox approach did not work.

This is my first attempt with Silverlight, so I might be missing something basic here.


There are a few ways to do this but I'll walk you through one of the the simplest (but not the purest from an architectural perspective).

Basically you want to find out when the selection of the ListBox changes. The ListBox raises a SelectionChanged event which can be listened to in the code behind.

        <ListBox x:Name="List1" ItemsSource="{Binding}" SelectionChanged="SelectionChangedHandler" SelectionMode="Single" >
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding}" FontSize="20"/>  
                 </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

Then have a handler something like:

private void SelectionChangedHandler(object sender, SelectionChangedEventArgs e)
{
    IList selectedItems = e.AddedItems;
    string val = selectedItems.OfType<string>().FirstOrDefault();

    NavigationService.Navigate(new Uri(val));
}

One thing you'll need to be aware of is that ListBoxes support multiple selection. For this reason, the event arguments give you back a list of the selected items. For simplicity, all I've done is taken the first value from this list and used that as the navigation value. Notice how I've also set the SlectionMode property of the ListBox to Single which will ensure the user can only select one item.

If I were doing this for real I'd look into creating an TriggerAction tat can be hooked up to an event trigger through xaml which will remove the for code behinds. Take a look at this link if you're interesetd.


In addition to Chris' and James' replies, I'd add that you will also need to clear the listbox selection in the event handler, otherwise the user won't be able to tap the same item twice on the listbox (because the item will already be selected).

Using James' approach, I would change the SelectionChangedHandler() implementation as follows:

private void SelectionChangedHandler(object sender, SelectionChangedEventArgs e)
{
    // Avoid entering an infinite loop
    if (e.AddedItems.Count == 0)
    {
        return;
    }

    IList selectedItems = e.AddedItems;
    string val = selectedItems.OfType<string>().FirstOrDefault();

    NavigationService.Navigate(new Uri(val));

    // Clear the listbox selection
    ((ListBox)sender).SelectedItem = null;
}


What I would recommend is binding the SelectedItem property of the ListBox to a property in your ViewModel. Then, on the ListBox's SelectedItemChanged event, navigate to to the appropriate URL passing the data key on the QueryString, or upgrade to something like MVVM Light and put the actual SelectedItem object on the message bus for the child window to pick up. I have a sample of this second method on my Skydrive that you can check out.

HTH!
Chris

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜