Как получить доступ к внутреннему ItemsControl в ListBox в Windows Phone Silverlight - PullRequest
1 голос
/ 11 июня 2011

Я создаю небольшое приложение для Windows Phone, для которого в качестве основного элемента управления используется привязка данных ListBox. DataTemplate этого ListBox является элементом ItemsControl с привязкой к данным, который показывает, когда человек нажимает на элемент ListBox.

В настоящее время я обращаюсь к нему, просматривая визуальное дерево приложения и ссылаясь на него в списке, а затем получаю выбранный элемент через свойство SelectedIndex.

Есть ли лучший или более эффективный способ?

Этот работает в настоящее время , но я боюсь, что он останется эффективным в случае больших списков.

Спасибо

Ответы [ 2 ]

2 голосов
/ 11 июня 2011

Вы пробовали связать событие SelectionChanged ListBox?

<ListBox ItemsSource="{Binding}" SelectionChanged="ListBox_SelectionChanged">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <!-- ... -->
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

С этим в коде:

private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    ListBox listBox = sender as ListBox;

    // nothing selected? ignore
    if (listBox.SelectedIndex != -1)
    {
         // something is selected
    }

    // unselect the item so if they press it again, it takes the selection
    listBox.SelectedIndex = -1;
}
0 голосов
/ 11 июня 2011
ListBoxItem item = this.lstItems.ItemContainerGenerator.ContainerFromIndex(yourIndex) as ListBoxItem;

Затем вы можете использовать класс VisualTreeHelper для получения подэлементов

var containerBorder = VisualTreeHelper.GetChild(item, 0) as Border;
var contentControl = VisualTreeHelper.GetChild(containerBorder, 0);
var contentPresenter = VisualTreeHelper.GetChild(contentControl, 0);
var stackPanel = VisualTreeHelper.GetChild(contentPresenter, 0) as StackPanel; // Here the UIElement root type of your item template, say a stack panel for example.
var lblLineOne = stackPanel.Children[0] as TextBlock; // Child of stack panel
lblLineOne.Text = "Some Text"; // Updating the text.

Другой вариант - использовать службы класса GestureServices, доступные в WP7 Toolkit.

YouВам нужно будет добавить GestureListner к корневому элементу вашего DataTemplate следующим образом:

            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel>
                        <Controls:GestureService.GestureListener>
                            <Controls:GestureListener Tap="GestureListener_Tap" />
                        </Controls:GestureService.GestureListener>
                        <TextBlock x:Name="lblLineOne" Text="{Binding LineOne}" />
                        <TextBlock Text="{Binding LineTwo}" />
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>

И в обработчике событий GestureListener_Tap вы используете этот фрагмент.

    private void GestureListener_Tap(object sender, GestureEventArgs e)
    {
        var itemTemplateRoot = sender as StackPanel;
        var lbl1 = itemTemplateRoot.Children[0] as TextBlock;
        MessageBox.Show(lbl1.Text);
    }

I'mЯ не уверен, как GestureListner распознает внутренне прослушиваемый элемент, но я предполагаю, что он использует VisualTreeHelper, по крайней мере, этот метод более лаконичен.

...