Создание кнопки WPF с динамическим именем в XAML

У меня есть связанный ListBox в WPF, где у каждого элемента есть кнопка вверх/вниз для перемещения элемента вверх или вниз в списке.

Однако мне нужно знать, какая кнопка вызвала событие, поэтому я хочу установить имя кнопки в тип «UpButton» + listBoxItem.Text.

Вот упрощенная версия XAML

<ListBox>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition/>
                    <ColumnDefinition/>
                    <ColumnDefinition/>
                </Grid.ColumnDefinitions>

                <TextBlock Grid.Column="0" Text="{Binding Path=Position}"/>
                <Label Grid.Column="1"  Content="{Binding Path=Name}" FontSize="18" Margin="0,10,0,0" />
                <WrapPanel Grid.Column="2" >
                    <Button Click="MoveUpClick" Name="UpButton">Up</Button>
                    <Button Click="MoveDownClick" Name="DownButton">Down</Button>
                </WrapPanel>
            </Grid>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

Если кто-то знает об элементе управления, который обеспечивает аналогичную функциональность сортировки и / или с DragDrop для сортировки, я был бы признателен за любую помощь, поскольку я опоздал примерно на 2 часа, чтобы отправиться в отпуск.


person Mark    schedule 17.09.2009    source источник
comment
Марк, а зачем тебе знать название кнопки? Кажется, это не настоящий способ WPF...   -  person Max Galkin    schedule 17.09.2009
comment
(Только не поймите меня неправильно, я пытаюсь помочь, просто может быть лучший способ сделать это в WPF без текста)   -  person Max Galkin    schedule 17.09.2009
comment
Для каждого ListBoxItem есть две кнопки, поэтому, когда я получаю ClickEvent, мне нужно знать, какой ListBoxItem связан с кнопкой, которую я нажал. Я почти уверен, что есть более элегантный способ сделать это, просто у меня очень мало времени. Если у кого-то есть тип, чтобы объяснить правильный способ сделать это, я был бы рад.   -  person Mark    schedule 17.09.2009


Ответы (3)


Как сказал gimalay, в обработчике событий Click вы можете получить связанный элемент из контекста данных отправителя (как часть шаблона данных).

Button senderButton = sender as Button;
var item = senderButton.DataContext;

Предложение Джозефа было бы излишним для такой простой проблемы.

person Trainee4Life    schedule 18.09.2009

В обработчике события свойство Sender(button).DataContext будет установлено на элемент ItemsSource. Если вы хотите получить некоторый контроль, который каким-то образом связан с Sender, используйте VisualTreeHelper.

person gimalay    schedule 17.09.2009

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

namespace ListBoxExample
{
    public static class TagAttach
    {
        public static readonly System.Windows.DependencyProperty TagProperty = 
            System.Windows.DependencyProperty.RegisterAttached(
            "Tag", typeof (string), typeof (TagAttach));
        public static void SetTag(System.Windows.UIElement element, string value)
        {
            element.SetValue(TagProperty, value);
        }
        public static string GetTag(System.Windows.UIElement element)
        {
            return (string)element.GetValue(TagProperty);
        }
    }
}

<Window x:Class="ListBoxExample.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:loc="clr-namespace:ListBoxExample"
    Title="Window1" Height="300" Width="300">
    <Grid>
        <ListBox ItemsSource="{Binding}" Grid.IsSharedSizeScope="True">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition SharedSizeGroup="A" />
                            <ColumnDefinition SharedSizeGroup="B" />
                            <ColumnDefinition />
                        </Grid.ColumnDefinitions>

                        <TextBlock Grid.Column="0" Text="{Binding Position}"/>
                        <Label Grid.Column="1"  Content="{Binding Name}" FontSize="18" Margin="0,10,0,0" />
                        <WrapPanel Grid.Column="2" >
                            <Button Click="MoveUpClick" loc:TagAttach.Tag="{Binding Name}">Up</Button>
                            <Button Click="MoveDownClick" loc:TagAttach.Tag="{Binding Name}">Down</Button>
                        </WrapPanel>
                    </Grid>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
</Window>

namespace ListBoxExample
{
    public partial class Window1
    {
        public Window1()
        {
            InitializeComponent();
            DataContext = new[]
                {
                    new {Name = "Tom", Position = "Butcher"},
                    new {Name = "Dick", Position = "Baker"},
                    new {Name = "Harry", Position = "Candlestick Maker"}
                };
        }

        private void MoveUpClick(object sender, System.Windows.RoutedEventArgs e)
        {
            System.Windows.MessageBox.Show("Up - " + TagAttach.GetTag(sender as System.Windows.UIElement));
        }

        private void MoveDownClick(object sender, System.Windows.RoutedEventArgs e)
        {
            System.Windows.MessageBox.Show("Down - " + TagAttach.GetTag(sender as System.Windows.UIElement));
        }
    }
}
person Joseph Sturtevant    schedule 17.09.2009