Получить объект строки ListBox от кнопки, которая находится на DataTemplate

2

У меня есть ListBox с DataTemplate. Шаблон имеет Button на нем. Когда щелчок Button щелкнут, я хочу сделать некоторую логику с объектом, который является каждой строкой (в данном случае объектом называется WorkItemTypeMappings).

В OnClick как я могу перейти от Button (object sender) к объекту, который является строкой, на которой находится кнопка?

Вот XAML моего ListBox:

<ListBox ItemsSource="{Binding Source={StaticResource WorkItemTypeMappingsCollectionView}}" HorizontalContentAlignment="Stretch" ScrollViewer.HorizontalScrollBarVisibility="Disabled" Name="lstWITypes">
    <ListBox.GroupStyle>
        <x:Static Member="GroupStyle.Default"/>
    </ListBox.GroupStyle>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Grid HorizontalAlignment="Stretch">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="2*"/>
                    <ColumnDefinition Width="2*"/>
                    <ColumnDefinition Width="50"/>
                </Grid.ColumnDefinitions>
                <TextBlock Grid.Column="0" Text="{Binding SourceType, Converter={StaticResource WorkItemTypeToStringConverter}}"/>
                <ComboBox Grid.Column="1" SelectedItem="{Binding DestType}" ItemsSource="{Binding WorkItemTypesForCurrentDestProject, Source={x:Static loc:MainMediator.Instance}, diagnostics:PresentationTraceSources.TraceLevel=High}" DisplayMemberPath="Name" />

                <!-- This is the button-->
                <Button Grid.Column="2" Content="{Binding PercentMapped}" 
                        Click="ManualMappingClick"/>
            </Grid>
        </DataTemplate>                                        
    </ListBox.ItemTemplate>
</ListBox>
Теги:
wpf
listbox
wpf-controls

4 ответа

2
Лучший ответ

В качестве альтернативы вы можете использовать Command вместо Event. Если вы привязываете свою кнопку к команде и передаете вместе с ней параметр команды, вы должны иметь возможность получить элемент, связанный с этой кнопкой. Пример кода:

<!-- This is the button-->
 <Button
     Grid.Column="2"
     Content="{Binding PercentMapped}" 
     Command="SolutionNamespace:CommandClass.ButtonClickedCommand"
     CommandParameter="{Binding}" />

Я не уверен, насколько вы знакомы с командой WPF, но заметите, что CommandParameter связывается с контекстом без имени пути, то есть связывается с необходимыми WorkItemTypeMappings.

Код примера команды:

public static SimpleCommand ButtonClickedCommand { get; set; }

static CommandClass()
{
    ButtonClickedCommand = new SimpleCommand
                           {
                               ExecuteDelegate =
                               x=> ButtonClicked(x as WorkItemTypeMappings)
                           };
}


public static ButtonClicked(WorkItemTypeMappings mappings)
{
    if(mappings != null) MessageBox.Show(mapping.PercentMapped)
}

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

SimpleCommand - это просто упрощенная реализация ICommand, может ли это сделать Google, если вы не уверены. Я надеюсь, что это не будет излишним для вашей проблемы, но вы не можете ошибиться с командами WPF.

Удачи.

  • 0
    Хорошие вещи здесь. Я хотел попробовать свои силы в командах. Это будет хорошее испытание. Я попробую и приму, если получится.
  • 0
    Это работало фантастически! И я чувствую, что сделал это «правильным способом». Спасибо за отличный ответ.
Показать ещё 1 комментарий
1

Попробуйте использовать VisualTreeHelper, чтобы найти родительский ListBoxItem для кнопки. Несколько хороших общих универсальных вспомогательных функций можно найти здесь:

Как я могу найти элементы управления WPF по имени или типу?

чтобы, например, вы могли найти ListBoxItem из события click с вызовом, подобным этому:

ListBoxItem item = UIHelper.FindVisualParent<ListBoxItem>(sender);
  • 0
    Мне не нужен ListBoxItem. Мне нужны данные за этим. (Как я уже сказал в своем вопросе: «с объектом, который является каждой строкой (в данном случае это объект с именем WorkItemTypeMappings)»
  • 0
    ListBoxItem - это «данные за ним». Получив ListBoxItem, вы сможете просто привести его к следующему виду: WorkItemTypeMappings dataObject = item as WorkItemTypeMappings;
0

Кроме того, если у вас уже есть ссылка на ListBoxControl, и у вас также есть элемент данных, представляющий строку (я предполагаю, что, поскольку у вас есть привязка и, таким образом, можно вытащить ее из DataContext на кнопке), вы может запросить ItemsContainerGenerator. ContainerFromItem, чтобы дать вам фактическое значение UIElement для строки.

Элементcontainergenerator может быть найден как свойство в самом списке. (технически элемент управления элементами, так как он определен)

  • 0
    Я действительно хочу пойти другим путем. Мне нужен элемент данных, представляющий строку.
0

Вы пробовали ListBox.SelectedItem?

  • 1
    Да. Однако можно нажать кнопку и не выбирать пункт (я проверял)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню