ปุ่มในคอลัมน์รับแถวที่มาจากตัวจัดการเหตุการณ์คลิก


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 ของฉันหรือบางทีฉันอาจจะเป็นแบบวงเวียน? ความช่วยเหลือ / คำแนะนำใด ๆ ที่ชื่นชม

คำตอบ:


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) คุณสามารถสร้างคำสั่งใน Data Object (ViewModel) และปุ่มเรียกใช้คำสั่งเพื่อที่จะไม่มีรหัสใด ๆ อยู่ข้างหลังเช่นการคลิกปุ่ม
Jobi Joy

1
@JobiJoy: คุณมีตัวอย่างนี้โดยใช้ Command / RelayCommand หรือไม่? ฉันกำลังลองทำบางอย่าง แต่ไม่สามารถใช้งานได้ ..
VoodooChild

ปัญหาเกี่ยวกับตัวอย่างคำสั่งที่ฉันเคยเห็นคือคุณต้องสร้างฐานข้อมูลรายการที่เลือกดาต้ากริดให้กับสมาชิกของโมเดลมุมมองของคุณดังนั้นจึงเป็นการยากที่จะระบุขนาดคำสั่งให้เพียงพอสำหรับปุ่มลบ ฉันต้องการทรัพยากรคอลัมน์เทมเพลตปุ่มลบเพียงปุ่มเดียวที่ฉันสามารถใช้เพื่อลบอะไรก็ได้ในแอปของฉัน
Eric

47

อีกวิธีหนึ่งที่ฉันชอบทำคือผูก ID กับคุณสมบัติ 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;
}

เหตุใดคุณจึงผสมผสานเหตุการณ์และคำสั่งต่างๆ ใช้คำสั่งและใช้พารามิเตอร์คำสั่งในนั้น
ProfK

1
3 คำตอบ: ทำไมไม่? ความเรียบง่าย และ OP กำลังถามเกี่ยวกับตัวจัดการเหตุการณ์ไม่ใช่คำสั่ง คำสั่งอาจจะมากเกินไป การใช้CommandParameterอาจไม่ใช่การใช้งานตามวัตถุประสงค์ของคุณสมบัติ แต่ในทางความหมายมันมีความหมายมากกว่าการใช้Tagและง่ายกว่าการดึง ID จากวัตถุที่ถูกผูกไว้ในตัวจัดการ ถ้าคุณชอบคำสั่งวิธีนั้นก็ใช้ได้ แต่ทำไมต้องเพิ่มความซับซ้อนถ้าคุณจะไม่ใช้มัน?
xr280xr

11

อีกวิธีหนึ่งที่ผูกกับพารามิเตอร์คำสั่ง DataContext และเคารพ MVVM เช่น Jobi Joy พูดว่าปุ่มสืบทอดแถวฟอร์มข้อมูลบริบท

ปุ่มใน XAML

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

การใช้คำสั่ง

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

        }
    }

ดังนั้น RowActionCommand จะอยู่ใน Model หรือคุณจะรีเซ็ต datacontext ของปุ่มเป็น ViewModel
Tom Padilla

@ PetrŠebesta "RowActionCommand ถูกกำหนดไว้ในโมเดลมุมมองแต่ละแถว" นี่ไม่สมเหตุสมผลเลย แต่อย่างไรก็ตามทางออกที่ดี
Igor


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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.