Silverlight, как продвигать выбранный элемент списка при использовании кнопок в шаблонах данных - PullRequest
0 голосов
/ 10 августа 2011

В элементе управления Listbox у меня есть шаблон данных, который состоит из текста и кнопки.Учитывая характер Silverlight / WPF, когда я нажимаю кнопку внутри элемента списка, событие кнопки перехватывается до того, как выбран элемент списка.Поэтому, если я пытаюсь передать идентификатор записи выбранного элемента списка, в настоящее время я могу сделать это только сначала, нажав и выбрав элемент списка, а затем нажав кнопку.

Есть ли способ повысить выбор элемента списка, чтобы при создании элементов списка у меня была возможность нажать кнопку внутри элемента списка и вызвать какое-то событие (selectionChanged?), КотороеПозвольте мне захватить выбранный идентификатор записи и использовать его для некоторых других действий (передать в качестве параметра в метод и т. д.).Я использую простой инструментарий MVVM для этой реализации, поэтому мне было интересно, можно ли это обработать в viewModel или мне нужно будет обработать это в коде элементов управления, а затем перенести выбор в viewModel.Элемент управления со списком представлен в виде:

<ListBox x:Name="ResultListBox"
             HorizontalAlignment="Stretch"
             Background="{x:Null}"
             Grid.Row="1"
             BorderThickness="0" HorizontalContentAlignment="Stretch"
             ItemContainerStyle="{StaticResource ListBoxItemStyle1}"
             ItemsSource="{Binding SearchResults[0].Results}"
             ScrollViewer.HorizontalScrollBarVisibility="Disabled"
             Style="{StaticResource ListBoxStyle1}">

        <ListBox.ItemTemplate>

            <DataTemplate>
                <dts:TypeTemplateSelector Content="{Binding}" HorizontalContentAlignment="Stretch">
                    <!--  Template 1  -->
                    <formatter:TypeTemplateSelector.CFSTemplate>
                        <DataTemplate>
                            <qr:ucIndex_Product />
                        </DataTemplate>
                    </formatter:TypeTemplateSelector.CFSTemplate>

                    <!--  Template 2  -->
                    <formatter:TypeTemplateSelector.PersonTemplate>
                        <DataTemplate>
                            <qr:ucIndex_Person  />
                        </DataTemplate>
                    </formatter:TypeTemplateSelector.PersonTemplate>

            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

Внутри таблицы данных (пользовательский элемент управления) находится кнопка вместе с рядом других полей.Я опущу этот код в настоящее время, если не будет запрошено.

Заранее спасибо!

Ответы [ 3 ]

2 голосов
/ 10 августа 2011

Поместите это в ваш ListBox.Resources

<Style TargetType="{x:Type ListBoxItem}">
    <EventSetter Event="PreviewGotKeyboardFocus" Handler="SelectCurrentItem"/>
</Style>

И это в коде позади

protected void SelectCurrentItem(object sender, KeyboardFocusChangedEventArgs e)
{
    ListBoxItem item = (ListBoxItem)sender;
    item.IsSelected = true;
}

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

<Style TargetType="ListBoxItem">
  <Style.Triggers>
    <Trigger Property="IsKeyboardFocusWithin" Value="True">
      <Setter Property="IsSelected" Value="True" />
    </Trigger>
  </Style.Triggers>
</Style>

EDIT

Поскольку Silverlight не имеет EventSetters, вы можете использовать событие Loaded объекта ListBox и добавить следующее вваш код:

private void ResultListBox_Loaded(object sender, RoutedEventArgs e)
{
    ListBox list = (ListBox)sender;
    list.GotFocus += ResultListBox_GotFocus;
}

void ResultListBox_GotFocus(object sender, RoutedEventArgs e)
{
    var item = FindAncester<ListBoxItem>((DependencyObject)e.OriginalSource);
    if (item != null) item.IsSelected = true;
}

T FindAncester<T>(DependencyObject current) 
    where T : DependencyObject
{
    current = VisualTreeHelper.GetParent(current);

    while (current != null)
    {
        if (current is T)
        {
            return (T)current;
        }
        current = VisualTreeHelper.GetParent(current);
    };
    return null;
}

Это захватывает событие Focus для ListBox, принимает элемент управления, который вызвал событие focus, и перемещается вверх по визуальному дереву, чтобы найти объекты ListBoxItem, и устанавливает его Выбранное значение равнымправда.

1 голос
/ 16 марта 2012

rlcrews правильно поняли!Использовать DataContext:

ObservableCollection<Employee> employees1;
...
listBox1.ItemsSource = employees1;
...

//DataTemplate in ListBox has a button with following event
private void bnPromoteEmployee_Click(object sender, RoutedEventArgs e)
{
  Employee emp1 = (Employee)((Button)sender).DataContext;
  emp1.Promote();
}
1 голос
/ 13 августа 2011

Решение Рэйчел прекрасно работает.Единственная проблема, которую я обнаружил в этом подходе, заключалась в том, что он полностью фокусируется на выбранном элементе.В результате пользователю потребуется дважды щелкнуть внутри элемента управления, чтобы сосредоточить внимание на других элементах, таких как выбираемый текст или другая кнопка.Поработав с этим немного больше, я обнаружил, что вы также можете решить эту проблему, установив выбранные элементы списка в контекст данных объекта, на который вы щелкаете, и т. Д. Это хорошо работает и позволяет вам установить это для любого объекта пользовательского интерфейса в элементе управления.

   ListBox.SelectedItem = ((HyperlinkButton)sender).DataContext;

В этом примере у меня были кнопки гиперссылок в шаблоне данных.Нажав на них, вы установите фокус на выбранный элемент списка.

...