0

my question here is how to know which button is clicked. My buttons are bound to property of type ObservableCollection which contains objects of type Item and I need to use that object in my ViewModel when a button is clicked. Any ideas how to know which button is clicked? I had few ideas, like sending multiple Command Parameters (1.SelectedItems from ListBox 2.The Object from the button) or bind the object from the button to another property of type Item in the ViewModel after the button is clicked in order to use it. Any ideas will be apreciated.

I have this DataTemplate for buttons

<DataTemplate x:Key="ButtonTemplate">
            <WrapPanel>
                <Button x:Name="OrderButton"
                        FontSize="10"
                        Height="80" Width="80"
                        Content="{Binding Name}"
                        Command="{Binding OrderCommand, 
                                          Source={StaticResource OrderViewModel}}"
                        CommandParameter="{Binding ElementName=ListBoxUserControl, Path=SelectedItems}">
                </Button>
            </WrapPanel>
</DataTemplate>

My ViewModel

public class OrderViewModel : ObservableCollection<Order>, INotifyPropertyChanged
{ 
   public CreateOrderCommand CreateOrderCommand { get; set; }
   public ObservableCollection<Item> Data { get; set; }

 public OrderViewModel()
    {
        this.CreateOrderCommand = new CreateOrderCommand(this);
        DataObservableCollection data= new DataObservableCollection();
        Data = data;
    }
}

And I populate my buttons like this

<WrapPanel x:Name="OrderButtons">
            <ItemsControl   ItemTemplate="{StaticResource ButtonTemplate}"
                            ItemsSource="{Binding Data, Source={StaticResource OrderViewModel}}">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <WrapPanel Orientation="Horizontal">
                        </WrapPanel>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
            </ItemsControl>
    </WrapPanel>
  • Please describe what is your intention, not how your are trying to solve it, refer to http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem. In MVVM you should not care about what the ui control is. Your viewmodel(s) should be designed so that they handle things how you want. – Janne Matikainen Sep 14 '16 at 11:18
  • I want to use the Button's Data Context in my ViewModel and also send CommandParameter from another control from the same Button. – Yulian Linev Sep 14 '16 at 12:26

2 Answers2

1

Simply change the Button.CommandParameter binding to CommandParamter="{Binding}" if you want the data context of the button (i.e. the item from your items source) as the command parameter or, CommandParameter="{Binding RelativeSource={RelativeSource Self}}" if you want the actual button that was clicked.

ibebbs
  • 1,963
  • 2
  • 13
  • 20
  • I was aware of how to send the Button Data Context, but in this case, how can I send the Data Context of the Button and SelectedItems from a ListBox control as parameters? – Yulian Linev Sep 14 '16 at 12:24
1

First send the Button DataContext using the CommandParameter. To send the SelectedItem of your Listbox you can use

<Listbox SelectedItem="{Binding SelectedItem}"/> 

in your Listbox and make a SelectedItem property in your ViewModel.

private YourItemObject mySelectedItem;
    public YourItemObject SelectedItem
    {
        get { return mySelectedItem; }

        set
        {
             value = mySelectedItem
        }

Now you can use the SelectedItem in your ViewModel when the Button gets clicket. If you have multiple selections it gets a little bit more tricky ;).

private ButtonClicked(Parameter object)
{
   SelectedItem.UsingIt();
   if(object is YourButtonDataContext){
        YourButtonDataContext.UsingIt();
   }
}

Update with MultiSelection:

With Multiselection you have to do your own Listbox.

public class CustomListBox : ListBox
{
    public CustomListBox()
    {
        this.SelectionChanged += CustomListBox_SelectionChanged;
    }

    void CustomListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        this.SelectedItemsList = this.SelectedItems;
    }
    #region SelectedItemsList

    public IList SelectedItemsList
    {
        get { return (IList)GetValue(SelectedItemsListProperty); }
        set { SetValue(SelectedItemsListProperty, value); }
    }



    public static readonly DependencyProperty SelectedItemsListProperty =
            DependencyProperty.Register("SelectedItemsList", typeof(IList), typeof(CustomListBox), new PropertyMetadata(null));


    #endregion
}

In the ViewModel you have to have a property with the SelectedItems.

private IList mySelectedData = new List<SelectedDataObject>();
    public IList SelectedData
    {
        get { return mySelectedData ; }

        set
        {
            if (mySelectedData != value)
            {
                mySelectedData = value;
                RaisePropertyChanged(() => SelectedData);
            }
        }
    }

The XAML Looks like this:

<local:CustomListBox ItemsSource="{Binding YourList}" SelectionMode="Extended" SelectedItemsList="{Binding SelectedData, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
    ...
</local:CustomListBox>

Source for Multiselection in DataGrid is: https://stackoverflow.com/a/22908694/3330227

Community
  • 1
  • 1
altohr
  • 11
  • 2
  • I actually did that, but I have multiple selections. Can you help me with a solution? – Yulian Linev Sep 14 '16 at 13:13
  • Update it. I have done it with a Datagrid. i hope it works the same with the Listbox. – altohr Sep 14 '16 at 13:26
  • I quickly used this article http://grokys.blogspot.bg/2010/07/mvvm-and-multiple-selection-part-i.html And managed to make my program work, but when the listbox is in template, it selects each item in every listbox. I will check your answer and try to implement it. When I am done I will pick an answer. Thank you for your help. – Yulian Linev Sep 14 '16 at 13:34