czwartek, 17 maja 2012

MouseLeftButtonDown na DataGrid

Ostatnio spotkałem się z pewnym problemem związanym z DataGridem. Potrzebowałem oprogramować na nim zdarzenie MouseLeftButtonDown. Jednak nie jest to takie proste. Do pokazania problemu i rozwiązania użyję prostego projektu Silverlight Application.

Tworzenie projektu Silverlight

Utwórzmy zwykły najprostrzy projekt Silverlight Application w Visual Studio.
Za pomocą toolboxa lub bezpośrednio w XAML dodajmy do niego obiekt DataGrid.
Utwórzmy dodatkowo nową klasę Person, której obiektami wypełnimy automatycznie DataGrida. Tutaj przykład klasy:

    public class Person
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }

Następnie zaraz po InitializeComponent() w metodzie MainPage() zapiszmy 100 losowych osób do naszego DataGrida.
        List<person> persons = new List<person>();
        for(int i=0;i<100;++i){
            persons.Add(new Person{ FirstName = "Name " + i, LastName = "LastName " + i});
        }
        dataGrid1.AutoGenerateColumns = true;
        dataGrid1.ItemsSource = persons;

Po uruchomieniu projektu powinniśmy zobaczyć wynik podobny do tego:

Problem

Aby przekonać się o problemie MouseLeftButtonDown spróbujmy dopisać reagowanie na to właśnie zdarzenie poprzez wyświetlenie MessageBoxa. Tutaj przykładowa metoda:
private void dataGrid1_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    MessageBox.Show("Mouse Pressed!");
}

Zauważymy że tylko po kliknięciu na górną belkę z nazwami kolumn lub na jedno-pixelową obwódkę wokół naszej kontrolki następuje wyświetlenie MessageBoxa:

A co jeśli np tak jak ja, potrzebujemy koniecznie wyzwolić to zdarzenie po kliknięciu na dany rekord wewnątrz kontrolki? Jak zrobić żeby nasz event nie został "zjedzony" przez wiersze tabeli?

Rozwiązanie problemu

Utworzymy własną kontrolkę dziedziczącą po  DataGrid.
public class MyDataGrid : DataGrid
{
    public MyDataGrid()
    {
        this.AddHandler(FrameworkElement.MouseLeftButtonDownEvent, new MouseButtonEventHandler(MouseDown), true);
    }
    void MouseDown(object sender, MouseButtonEventArgs e)
    {
        MessageBox.Show("Mouse Left Button Down!");
    }
}

Konstruktor naszego nowego obiektu wywołuje metodę AddHandler, która doda odpowiedni Event do obsłużenia. Dodatkowo jako parametr musimy podać nowy obiekt MouseButtonEventHandler który inicjujemy podając mu nazwę metody wywoływanej przy wciśnięciu lewego przycisku myszki.

Z poprzedniego pliku MainPage.xaml.cs usuńmy wcześniej dopisaną metodę dataGrid1_MouseLeftButtonDown() pamiętając o usunięciu jej także z pliku xaml.
Dodatkowo w pliku xaml zdefiniujmy naszą przestrzeń nazw, w tym przypadku:
xmlns:my="clr-namespace:SilverlightApplication1"

Możemy teraz zmienić znacznik <sdk:datagrid> na <my:mydatagrid> pamiętając o zmianie parametru Name na x:Name.
Jeśli wszystko wykonaliśmy dobrze to po kliknięciu na dane w naszym nowym DataGridzie uzyskamy obsługę zdarzenia kliknięcia lewego przycisku myszki:
Poniżej całkowity kod MainPage.xaml.cs:
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace SilverlightApplication1
{
    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();
            List persons = new List();
            for(int i=0;i<100;++i){
                persons.Add(new Person{ FirstName = "Name " + i, LastName = "LastName " + i});
            }
            dataGrid1.AutoGenerateColumns = true;
            dataGrid1.ItemsSource = persons;
        }
    }

    public class Person
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }
}


MainPage.xaml:


    
        
    



MyDataGrid.cs:
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace SilverlightApplication1
{
    public class MyDataGrid : DataGrid
    {
        public MyDataGrid()
        {
            this.AddHandler(FrameworkElement.MouseLeftButtonDownEvent, new MouseButtonEventHandler(MouseDown), true);
        }
        void MouseDown(object sender, MouseButtonEventArgs e)
        {
            MessageBox.Show("Mouse Left Button Down!");
        }
    }
}



Brak komentarzy:

Prześlij komentarz