Как я могу использовать функцию С# для доступа к элементу управления WPF, который ее вызвал?

Я работаю над редактором игровых уровней в WPF, используя С#.

У меня есть ряд элементов управления изображениями для выбора текстур, и я хочу, чтобы каждое изображение можно было щелкнуть, с некоторой видимой обратной связью, чтобы показать, какое из них выбрано.

Вот один из элементов управления изображением вместе с зеленой рамкой выделения, которая появляется при нажатии:

<Image x:Name="tile_image1" Source="as asphalt_test.png" Stretch="Fill" HorizontalAlignment="Right" VerticalAlignment="Top" Width="50" Height="50" MouseDown="texture_click" Margin="0,93,69,0" RenderTransformOrigin="0.16,2.04"/>
<Border x:Name="tile_border" BorderBrush="Lime" BorderThickness="3" HorizontalAlignment="Right" Height="54" Margin="0,91,65,0" VerticalAlignment="Top" Width="54" Visibility="Hidden" />

Мой вопрос касается функции «texture_click».

Я хочу повторно использовать одну и ту же функцию для каждого элемента управления изображением, которую я могу легко назначить с помощью атрибута MouseDown в XAML. Однако я не знаю, как внутри функции определить, какой элемент управления ее вызвал, или как получить доступ к свойствам этого элемента управления, например ".Source". Я хочу иметь возможность получить имя файла изображения, а также переместить координаты зеленой границы за новым выделением.

Прямо сейчас я просто жестко закодировал его для первого элемента управления изображением. Щелчки по другим изображениям вызовут функцию, но функция выберет только первое изображение (не то, которое было на самом деле нажато).

// click on tile 1
private void texture_click (object sender, MouseButtonEventArgs e)
  {
  tile_border.Visibility = Visibility.Visible;

  current_tilefile = tile_image1.Source;
  string source_string = Convert.ToString (tile_image1.Source);
  int last_slash = source_string.LastIndexOf ('/');
  current_tile = source_string.Substring (last_slash + 1, 3);
  }

Я попытался использовать «отправитель», так как подумал, что это может быть объект, вызвавший функцию, но это вернуло ошибку. Я также пытался вызвать функцию с помощью «texture_click (this)», но это тоже не помогло. Это были, по общему признанию, полные кадры в темноте, так что я не удивился.

Я все еще довольно новичок в этом программном обеспечении, поэтому любое понимание, которое вы, ребята, можете дать, было бы здорово.


person Nightmare Games    schedule 20.08.2014    source источник
comment
sender должен быть объектом, вызвавшим событие. Какую ошибку вы получили? Вы убедились, что привели object sender к соответствующему типу элемента управления?   -  person Basic    schedule 20.08.2014
comment
какая у тебя ошибка?   -  person Rang    schedule 20.08.2014
comment
Ошибка: объект не содержит определения источника. @Basic: я не понял ваш вопрос о типе элемента управления, пока не прочитал ответ МакГарнагла ниже. Я думаю, что отправитель как бит изображения - это то, о чем вы говорили.   -  person Nightmare Games    schedule 24.08.2014
comment
@NightmareGames Да, это то, что я имел в виду, извините, если я был неясен. Рад, что ты разобрался.   -  person Basic    schedule 24.08.2014


Ответы (1)


Вам просто нужно привести параметр sender к типу элемента управления (в данном случае Image):

private void texture_click (object sender, MouseButtonEventArgs e)
{
    //tile_border.Visibility = Visibility.Visible;
    var image = sender as Image;
    if (image != null)
    {
        current_tilefile = image.Source;
        string source_string = image.Source.ToString();
        int last_slash = source_string.LastIndexOf ('/');
        current_tile = source_string.Substring (last_slash + 1, 3);
    }
}

Конечно, это не дает вам доступа к соответствующей границе. Одна вещь, которую вы можете сделать, это просто сбросить границу в свойство Tag изображения:

<Image x:Name="tile_image1" ... Tag="{Binding ElementName=tile_border}" />
<Border x:Name="tile_border" ... />

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

private void texture_click (object sender, MouseButtonEventArgs e)
{
    var image = sender as Image;
    if (image != null)
    {
        var border = image.Tag as Border;
        if (border != null)
        {
            border.Visibility = Visibility.Visible;
        }
        // ...
    }
}

Обратите внимание, что это (манипулирование элементами пользовательского интерфейса из кода программной части) не является идеальным способом написания приложения WPF. Обычно вы делаете что-то подобное, используя существующий элемент управления (например, ToggleButton) и переписывая его ControlTemplate так, чтобы его визуальное состояние IsChecked отображало границу. Но я понимаю, что это бред...

person McGarnagle    schedule 20.08.2014
comment
Это то, что я искал - спасибо. Я пытался получить доступ к sender.Source, но он выдавал ошибку, из-за которой я думал, что ищу не в том месте. Я не знал, что должен указать отправителя как изображение. - person Nightmare Games; 24.08.2014
comment
Ваши советы о том, как сделать это по-другому, меня заинтриговали. Имея опыт работы в играх и веб-дизайне, я мало работал с формами Windows, и до сих пор я подходил к WPF так же, как к написанию программы на Javascript/jQuery. - person Nightmare Games; 24.08.2014