Jak użyć Sender'a dla swojej klasy?

0

Witam, pracuje sobie nad pewną prostą gierką która ma być aplikacją WPF. Dynamicznie tworzę tablicę obrazów (klasy Image) i rysuje je na ekranie rozmieszczając jako kratki szachownicy. Następnie przypisuje tą tablicę to tablicy obiektów mojej klasy "Pole" która będzie przechowywać pewne informacje o tychże polach, dla uproszczenia powiedzmy, że będzie to pierwsza współrzędna danego pola. Następnie chcę, aby po kliknięciu na dany obrazek, w messegebox'ie wyświetlała się jego współrzędna x. Próbowałem do tej pory bawić się Senderem. Dopisałem, żeby klasa Pole dziedziczyła po klasie Image, żeby działało dla niej "MouseDown"

Tak wygląda moja klasa:

public class Pole:Image
    {
        public int x;
        public Image ikona;               
    } 

a tak main:

 
Pole[,] tab = new Pole[8, 8];
.
.
.
foreach (Pole p in pole)
                p.MouseDown += Klik;

a tak funkcja:

private void Klik(object sender, EventArgs e)
        {
            Pole a = (sender as Pole);
            MessageBox.Show(a.x.ToString());
        }
 

Jednak po uruchomieniu programu i kliknięciu na obrazek nic się nie dzieje. Z góry dziękuję za pomoc, pozdrawiam :)

0

Zmień pętlę z foreach na for. Pętla foreach iteruje obiekty tylko do odczytu.
Tak naprawdę iterując za pomocą foreach operujesz na kopii gdyż poszczególne obiekty w kolekcji są zwracane przez wartość.

Możesz do tego eventu napisać prostą lambdę. Będzie czytelniej:

p.MouseDown += (sender,e)=>{
     var field = sender as Field;
     MessageBox.Show(field.PosX.ToString());
}

Poza tym:

  • używaj angielskich nazw;
  • nie używaj jednoliterowych nazw obiektów;
  • publiczne pola klasy nazywaj rozpoczynając z wielkiej litery;
  • używaj słówka var tak jak w przykładzie, bo jest czytelniej.
  • nie używaj tablic tylko kolekcji np. List<List<Field>> w Twoim przypadku.
0
for (int j = field.GetLength(1) - 1; j >= 0; j--)
           {
                for (int i = field.GetLength(0) - 1; i >= 0; i--)
               {
                    field[i, j].MouseDown += Klik;
                    
               }
           }
 private void Klik(object sender, EventArgs e)
        {
            var field = (sender as Field);
            MessageBox.Show(field.PosX.ToString());
        }
 

poprawiłem na coś takiego, ale w dalszym ciągu nic się nie dzieje po kliknięciu :/

1

@somekind Fakt, masz rację.

@Cycman jak to Ci nie działa? Popatrz:

        public MainWindow() {
            InitializeComponent();

            var list = new List<List<Image>> {
                new List<Image> { new Image(), new Image(), new Image(), new Image() },
                new List<Image> { new Image(), new Image(), new Image(), new Image() },
                new List<Image> { new Image(), new Image(), new Image(), new Image() },
            };

            this.MainGrid.ShowGridLines = true;

            for (int i = 0; i < list.Count; ++i) {
                this.MainGrid.ColumnDefinitions.Add(new ColumnDefinition());

                for (int j = 0; j < list[i].Count; ++j) {
                    if (i == 0) this.MainGrid.RowDefinitions.Add(new RowDefinition());

                    list[i][j].Width = 120;
                    list[i][j].Source = new BitmapImage(new Uri(@"pack://application:,,,/4programmersWPF;component/accept.png"));
                    list[i][j].MouseDown += (sender, e) => { MessageBox.Show("Traf!"); };                    

                    Grid.SetRow(list[i][j], j);
                    Grid.SetColumn(list[i][j], i);
                    this.MainGrid.Children.Add(list[i][j]);
                }
            }
        }

Do XAML'a dodaj:

<Grid Name="MainGrid"/>

I działa, w którykolwiek obrazek bym nie nacisnął:

eb4c647b82.png

0

Ale nie o to mi chodziło, ja chce, żeby klasa Field przechowywała właściwości każdego pola, PosX to był zły przykład, bo mamy do tego dostęp już z Image, powiedzmy, że klasa wyglada tak:

 
 public class Field : Image
    {
        public bool available;
        public Image icon;         
    }

przy czym available będzie nam mówić, czy można postawić na tym polu pionek czy nie. Próbowałem podmienić trochę rzeczy w tym kodzie:

public MainWindow()
        {
            InitializeComponent();

            var list = new List<List<Image>> {
                new List<Image> { new Image(), new Image(), new Image(), new Image() },
                new List<Image> { new Image(), new Image(), new Image(), new Image() },
                new List<Image> { new Image(), new Image(), new Image(), new Image() },
            };

            var list2 = new List<List<Field>> {
                new List<Field> { new Field(), new Field(), new Field(), new Field() },
                new List<Field> { new Field(), new Field(), new Field(), new Field() },
                new List<Field> { new Field(), new Field(), new Field(), new Field() },
            };


            this.MainGrid.ShowGridLines = true;

            for (int i = 0; i < list.Count; ++i)
            {
                this.MainGrid.ColumnDefinitions.Add(new ColumnDefinition());

                for (int j = 0; j < list[i].Count; ++j)
                {
                    if (i == 0) this.MainGrid.RowDefinitions.Add(new RowDefinition());

                    list[i][j].Width = 120;
                    list[i][j].Source = new BitmapImage(new Uri("Owca.jpg", UriKind.Relative));                
                    Grid.SetRow(list[i][j], j);
                    Grid.SetColumn(list[i][j], i);
                    this.MainGrid.Children.Add(list[i][j]);

                    list2[i][j].icon = list[i][j];
                    list2[i][j].available = true;

                    list2[i][j].MouseDown += (sender, e) =>
                    {
                        var field = sender as Field;
                        MessageBox.Show(field.available.ToString());
                    };
                }
            }
        }
 

ale nadal nie działa

1

No, bo namieszałeś w ogóle. Po co Ci w klasie Filed pole klasy Image skoro Twoja klasa dziedziczy od Image i posiada wszystkie jej własności? :)
Po co w pętli robisz tak: list[i][j].Source = new BitmapImage(new Uri("Owca.jpg", UriKind.Relative)); żeby później operować na obiektach drugiej listy? To się wszystko nie trzyma kupy przecież.

namespace _4programmersWPF {
    class Field : Image {
        public bool IsAvailble { get; set; }
        public Field() {
            this.IsAvailble = false;
        }
    }

    public partial class MainWindow : Window {
        public MainWindow() {
            InitializeComponent();

            var list = new List<List<Field>> {
                new List<Field> { new Field(), new Field(), new Field(), new Field() },
                new List<Field> { new Field(), new Field(), new Field(), new Field() },
                new List<Field> { new Field(), new Field(), new Field(), new Field() },
            };

            this.MainGrid.ShowGridLines = true;

            for (int i = 0; i < list.Count; ++i) {
                this.MainGrid.ColumnDefinitions.Add(new ColumnDefinition());

                for (int j = 0; j < list[i].Count; ++j) {
                    if (i == 0) this.MainGrid.RowDefinitions.Add(new RowDefinition());

                    list[i][j].Width = 120;
                    list[i][j].Source = new BitmapImage(new Uri(@"pack://application:,,,/4programmersWPF;component/accept.png"));
                    list[i][j].MouseDown += (sender, e) => { MessageBox.Show((sender as Field).IsAvailble.ToString()); };

                    Grid.SetRow(list[i][j], j);
                    Grid.SetColumn(list[i][j], i);
                    this.MainGrid.Children.Add(list[i][j]);
                }
            }
        }
    }
}

I to działa. Już mi się nie chce screena dawać no :)

0

O rany, faktycznie trochę pokaszaniłem :P Działa :) Wielkie dzięki za pomoc i wszystkie rady, świeżak jestem i każdy taki tip jest na wagę złota :D

1 użytkowników online, w tym zalogowanych: 0, gości: 1