7

I am trying to build a WPF application (using C#.net) in which I want to add button inside ListBox.

Here is the data template which I have placed in the resource dictionary

<DataTemplate x:Key="MYTemplate">
    <StackPanel Margin="4">
        <DockPanel>
            <TextBlock Text="ISBN No:" DockPanel.Dock="Left" Margin="5,0,10,0" Foreground="AliceBlue" />
            <TextBlock Text="            " />
            <TextBlock Text="{Binding ISBN}" Foreground="LimeGreen" FontWeight="Bold" />
        </DockPanel>
        <DockPanel>
            <TextBlock Text="Book Name:" DockPanel.Dock="Left" Margin="5,0,10,0" Foreground="AliceBlue"/>
            <TextBlock Text="       " />
            <TextBlock Text="{Binding BookName}" Foreground="LimeGreen"  FontWeight="Bold" />
        </DockPanel >
        <DockPanel >
            <TextBlock Text="Publisher Name:" DockPanel.Dock="Left" Margin="5,0,10,0" Foreground="AliceBlue" />
            <TextBlock Text=" " />
            <TextBlock Text="{Binding PublisherName}" Foreground="LimeGreen" FontWeight="Bold"  />
        </DockPanel>
        <DockPanel>
            <Button Name="MyButton" Content="Click Me">

            </Button>
        </DockPanel>
    </StackPanel>
</DataTemplate>

How do add the click event to the button tag in the above template? Also where should I place the method which will be called when button is clicked.

Nilesh Barai
  • 1,312
  • 8
  • 22
  • 48
  • possible duplicate : http://stackoverflow.com/q/697276/312462 – Yeonho Feb 11 '12 at 08:39
  • If you use events and not commands, then see my answer http://stackoverflow.com/a/30727398/254109 – xmedeko Jun 09 '15 at 09:00
  • @xmedeko: Commands have advantages over events like we can assign shorcut key for a command, we can specifically evaluate whether to execute it or not, etc. – Nilesh Barai Jun 09 '15 at 21:06
  • @Nilesh Barai yep, command is preferable solution. I have added how to use event as an alternative. And you asked for *click event*. – xmedeko Jun 11 '15 at 05:04

1 Answers1

16

Nilesh,

you should be using binding the button to a command. For example if your data item is defined like this:

public class MyItem : ViewModelBase
{
    public MyItem()
    {
        ClickMeCommand = new RelayCommand(ClickMe);
    }

    private void ClickMe()
    {
        Debug.WriteLine("I was clicked");
    }

    public string ISBN { get; set; }
    public string BookName { get; set; }
    public string PublisherName { get; set; }

    public ICommand ClickMeCommand { get; set; }
}

Then this will invoke the ClickMe method.

<DockPanel>
    <Button Content="Click Me" Command="{Binding ClickMeCommand}" />
</DockPanel>

Or you can put the command in the parent view model:

public class MainViewModel : ViewModelBase
{
    public IEnumerable<MyItem> Items { get; private set; }

    /// <summary>
    /// Initializes a new instance of the MainViewModel class.
    /// </summary>
    public MainViewModel()
    {
        Items = new List<MyItem>
                    {
                        new MyItem{ ISBN = "ISBN", BookName = "Book", PublisherName = "Publisher"}
                    };
        ClickMeCommand = new RelayCommand<MyItem>(ClickMe);
    }

    private void ClickMe(MyItem item)
    {
        Debug.WriteLine(string.Format("This book was clicked: {0}", item.BookName));
    }

    public ICommand ClickMeCommand { get; set; }

}

and bind to that

<DockPanel>
    <Button Content="Click Me" CommandParameter="{Binding}" Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ListBox}}, Path=DataContext.ClickMeCommand}" />
</DockPanel>

Note that the code above is using MVVM light and I'm assuming you have

  <ListBox ItemTemplate="{StaticResource MyTemplate}" ItemsSource="{Binding Items}"/>
Phil
  • 42,255
  • 9
  • 100
  • 100
  • 1
    @Phil thanks Phil, i am using the DataTemplate in separate file, the binding in: is not working for me, can you help me? – Anas Mar 20 '14 at 05:46