Nút trong một cột, nhận hàng mà từ đó nó đến trên trình xử lý sự kiện Nhấp chuột


97

Tôi đã đặt nguồn item của WPF Datagrid thành Danh sách các đối tượng được trả về từ DAL của mình. Tôi cũng đã thêm một cột bổ sung chứa một nút, xaml ở bên dưới.

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

Điều này hiển thị tốt. Tuy nhiên trên phương thức Button_Click , có cách nào tôi có thể lấy hàng trên datagrid nơi nút nằm không? Cụ thể hơn, một trong những thuộc tính của các đối tượng của tôi là "Id" và tôi muốn có thể chuyển nó vào hàm tạo của một biểu mẫu khác trong trình xử lý sự kiện.

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

Có lẽ tôi cần một cái gì đó bổ sung trong xaml của tôi, hoặc có thể tôi đang nói về điều này một cách đường vòng? Bất kỳ sự trợ giúp / lời khuyên nào được đánh giá cao.

Câu trả lời:


128

Về cơ bản, nút của bạn sẽ kế thừa văn bản dữ liệu của một đối tượng dữ liệu hàng. Tôi đang gọi nó là MyObject và hy vọng MyObject.ID là những gì bạn muốn.

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
Cách lý tưởng để thực hiện loại công việc này là sử dụng các lệnh (Về cơ bản là mẫu MVVM), bạn có thể tạo một lệnh trong Đối tượng dữ liệu (ViewModel) của mình và gọi Button.Command, Vì vậy, sẽ không có bất kỳ mã nào phía sau như Nhấp vào nút.
Jobi Joy

1
@JobiJoy: bạn có ví dụ về điều này bằng cách sử dụng Command / RelayCommand không? Tôi đang cố gắng vài thứ nhưng không thể làm cho nó làm việc ..
VoodooChild

Vấn đề với các ví dụ lệnh mà tôi đã thấy là bạn phải lập dữ liệu mục đã chọn trong lưới dữ liệu cho một thành viên của mô hình chế độ xem của bạn và do đó, thật khó để tổng quát hóa lệnh đủ tốt cho một nút xóa. Tôi muốn một tài nguyên cột mẫu nút xóa mà tôi có thể sử dụng để xóa khá nhiều thứ trong ứng dụng của mình.
Eric

47

Một cách khác mà tôi thích làm điều này là liên kết ID với thuộc tính CommandParameter của nút:

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

Sau đó, bạn có thể truy cập nó như vậy trong mã:

private void Button_Click(object sender, RoutedEventArgs e)
{
    object ID = ((Button)sender).CommandParameter;
}

Tại sao bạn trộn lẫn các sự kiện và lệnh? Sử dụng một Lệnh và sử dụng tham số lệnh trong đó.
ProfK

1
3 câu trả lời: Tại sao không? Sự đơn giản. Và OP đang hỏi về trình xử lý sự kiện, không phải lệnh. Một lệnh có thể quá mức cần thiết. Việc sử dụng CommandParametercó thể không phải là mục đích sử dụng của thuộc tính, nhưng về mặt ngữ nghĩa, nó có ý nghĩa hơn việc sử dụng Tagvà đơn giản hơn việc lấy ID từ đối tượng bị ràng buộc trong trình xử lý. Nếu bạn thích Lệnh hơn, cách tiếp cận đó cũng tốt, nhưng tại sao lại thêm phức tạp nếu bạn không sử dụng nó?
xr280xr

10

Một cách khác liên kết với tham số lệnh DataContext và tôn trọng MVVM như Jobi Joy nói rằng nút kế thừa hàng biểu mẫu datacontext.

Nút trong XAML

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

Thực hiện lệnh

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

        }
    }

Vì vậy, RowActionCommand sẽ nằm trong Model hay bạn sẽ đặt lại văn bản dữ liệu của nút thành ViewModel?
Tom Padilla

@ PetrŠebesta "RowActionCommand được định nghĩa trong mỗi mô hình xem hàng." Điều này không có ý nghĩa gì. Nhưng dù sao, giải pháp tốt.
Igor

4
MyObject obj= (MyObject)((Button)e.Source).DataContext;

0

Nếu DataContext của DataGrid của bạn là một đối tượng DataView (thuộc tính DefaultView của DataTable), thì bạn cũng có thể thực hiện việc này:

private void Button_Click(object sender, RoutedEventArgs e) {
   DataRowView row = (DataRowView)((Button)e.Source).DataContext;
}

Nó nên được e.OriginalSource. thay vì e.Source.
Bigeyes

Nghiêm túc đấy Bigeyes, câu trả lời của tôi là từ mã thực, trực tiếp, làm việc!
SurfingSanta
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.