views:

674

answers:

3

I have a bound ListBox in WPF where each item has an up / down button to move the item up or down in the list box.

However I need to know which button fired the event so I want to set the name of the button to "UpButton" + listBoxItem.Text type of thing.

Here's a simplified version of the 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>

If somebody knows of a control out there that provides similar sorting functionality and / or with DragDrop to sort it, I'd appreciate any help as I'm about 2 hours overdue for heading off on holiday.

A: 

In the event handler Sender(button).DataContext property will be set to ItemsSource item. If you want get some control, that somehow related to Sender, use VisualTreeHelper.

gimalay
A: 

Like Yacoder said, there is definitely a more elegant way to do this. If, however, you want to go with the dynamic name approach, you should be able to make it work using an attached property like so:

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));
        }
    }
}
Joseph Sturtevant
+1  A: 

As gimalay said, in the Click event handler, you can get the associated item from the sender's data context (as it part of the data template).

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

Joseph's suggestion would be an overkill for a simple problem like this.

Trainee4Life