Кнопка в столбце, получение строки, из которой она пришла в обработчик события Click

98

Я установил itemsource моего WPF Datagrid в список объектов, возвращаемых из моего DAL. Я также добавил дополнительный столбец, содержащий кнопку, xaml находится ниже.

<toolkit:DataGridTemplateColumn  MinWidth="100" Header="View">
    <toolkit:DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <Button Click="Button_Click">View Details</Button>
        </DataTemplate>
    </toolkit:DataGridTemplateColumn.CellTemplate>
</toolkit:DataGridTemplateColumn>

Это нормально. Однако в методе Button_Click есть ли способ получить строку в сетке данных, где находится кнопка? В частности, одним из свойств моих объектов является «Id», и я хотел бы иметь возможность передать его в конструктор другой формы в обработчике событий.

private void Button_Click(object sender, RoutedEventArgs e)
    {
        //I need to know which row this button is on so I can retrieve the "id"  
    }

Возможно, мне нужно что-то дополнительное в моем xaml, или, может быть, я собираюсь об этом окольным путем? Любая помощь / совет приветствуются.

RekrowYnapmoc
источник

Ответы:

128

Обычно ваша кнопка наследует текст объекта данных строки. Я называю его MyObject и надеюсь, что MyObject.ID - это то, что вам нужно.

private void Button_Click(object sender, RoutedEventArgs e)
{
    MyObject obj = ((FrameworkElement)sender).DataContext as MyObject;
    //Do whatever you wanted to do with MyObject.ID
}
Джоби Джой
источник
7
Идеальный способ делать такие вещи - использовать команды (в основном шаблон MVVM), вы можете создать команду в своем объекте данных (ViewModel) и вызвать Button.Command, чтобы не было никакого кода, такого как нажатие кнопки.
Jobi Joy
1
@JobiJoy: есть ли у вас пример использования Command / RelayCommand? Я пробую несколько вещей, но не могу заставить их работать ..
VoodooChild
Проблема с примерами команд, которые я видел, заключается в том, что вам нужно привязать выбранный элемент datagrid к члену вашей модели представления, и, таким образом, сложно обобщить команду, достаточную для использования кнопки удаления. Мне нужен один ресурс столбца шаблона кнопки удаления, который я могу использовать для удаления практически всего в моем приложении.
Эрик
47

Еще один способ сделать это - привязать идентификатор к свойству CommandParameter кнопки:

<Button Click="Button_Click" CommandParameter="{Binding Path=ID}">View Details</Button>

Затем вы можете получить к нему доступ, например, в коде:

private void Button_Click(object sender, RoutedEventArgs e)
{
    object ID = ((Button)sender).CommandParameter;
}
xr280xr
источник
Почему вы путаете события и команды? Используйте команду и используйте в ней параметр команды.
ProfK
1
3 ответа: Почему бы и нет? Простота. И OP спрашивает об обработчиках событий, а не о командах. Команда может быть излишней. Использование CommandParameterможет не являться предполагаемым использованием свойства, но семантически оно более значимо, чем использование, Tagи проще, чем получение идентификатора из связанного объекта в обработчике. Если вы предпочитаете команды, этот подход подходит, но зачем добавлять сложность, если вы не собираетесь его использовать?
xr280xr
10

Другой способ, который привязывается к параметру команды DataContext и уважает MVVM, например, Jobi Joy, говорит, что кнопка наследует строку формы datacontext.

Кнопка в XAML

<RadButton Content="..." Command="{Binding RowActionCommand}" 
                         CommandParameter="{Binding RelativeSource={RelativeSource Mode=Self}, Path=DataContext}"/>

Реализация команды

public void Execute(object parameter)
    {
        if (parameter is MyObject)
        {

        }
    }
Петр Шебеста
источник
Итак, будет ли RowActionCommand в модели или вы бы сбросили контекст данных кнопки на ViewModel?
Том Падилла
@ PetrŠebesta "RowActionCommand определяется в каждой модели представления строки". В этом нет никакого смысла. Но в любом случае хорошее решение.
Игорь
4
MyObject obj= (MyObject)((Button)e.Source).DataContext;
Шиха
источник
0

Если DataContext вашего DataGrid является объектом DataView (свойство DefaultView DataTable), вы также можете сделать это:

private void Button_Click(object sender, RoutedEventArgs e) {
   DataRowView row = (DataRowView)((Button)e.Source).DataContext;
}
СерфингСанта
источник
Так и должно быть e.OriginalSource. вместо e.Source.
Bigeyes
Серьезно Bigeyes, мой ответ - настоящий, живой, рабочий код!
SurfingSanta