Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ListBox selectedItem get working but set not working in MVVM

Tags:

c#

mvvm

wpf

listbox

I am working on a WPF application and following MVVM. In my view there is a grid view which contains different columns. One of these column is a ListBox. Now problem is that for the ListBox column, SelectedItem get works fine but set doesn't.

Here is my View code

<DataGrid ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}" SelectionMode="Single">
    <DataGrid.Columns>
        <DataGridTextColumn Binding="{Binding Name}" Header="Name" />
        <DataGridTemplateColumn Header="Actions">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <ListBox DisplayMemberPath="Name" ItemsSource="{Binding Actions}" SelectedItem="{Binding SelectedAction}" />
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>

In my ViewModel, I have Main ViewModel class, which contains a list of Items. Item class contains name, a list of actions and selected action.

public class MyViewModel : INotifyOfPropertyChanged
{
    private ObservableCollection<Item> _items;
    public ObservableCollection<Item> Items
    {
        get { return _items?? (_items= new ObservableCollection<Item>); }
    }

    private Item _selectedItem;
    public Item SelectedItem
    {
        get { return _selectedItem; }
        set { _selectedItem= value; }
    }
}

public class Item : INotifyOfPropertyChanged
{
    public string Name;

    private ObservableCollection<string> _actions;
    public ObservableCollection<string> Actions
    {
        get { return _actions?? (_actions= new ObservableCollection<string>); }
    }

    private string _selectedAction;
    public string SelectedAction
    {
        get { return _selectedAction; }
        set { _selectedAction = value; }
    }
}

Now SelectedItem for Items list works fine. But SelectedItem insde Item class for Actions doesn't work completely. I inserted breakpoints on getter and setter of SelectedAction. get breakpoint hits. But if I select an action from the UI then set breakpoint for SelectedAction doesn't get hit.

What's the problem.

View

When I select Archive Project or Restore Project, setter of SelectedAction doesn't get called.

NOTE: I have removed unnecessary information like loading data in lists, implementation of INotifyOfPropertyChanged etc.

like image 673
fhnaseer Avatar asked May 14 '13 07:05

fhnaseer


People also ask

How to show selecteditem on the view using listbox in WPF?

The logic is quite simple. I’m passing a class item to ViewModel of type from which ListBox is bound to. And the WPF ViewModel will be assign a String value to the WPF TextBlock to show the selectedItem on the View. ListBox ItemSource and SelectionChanged method is defined in the design code and a TextBlock is made to show the SelectedItem.

How to bind isselected to selected items from DataGrid or listbox in MVVM?

Bind to SelectedItems from DataGrid or ListBox in MVVM Try creating an IsSelected property on each of your data items and binding ListBoxItem.IsSelected to that property <Style TargetType=" {x:Type ListBoxItem}"> <Setter Property="IsSelected" Value=" {Binding IsSelected, Mode=TwoWay}" /> </Style>

Is selecteditems a bindablecollection or a property?

Suspect that behaviour when SelectedItems was just a public member of BindableCollection, not a Property. Ah, I didn't realize that the property had to explicitly be called SelectedItems (mine was called SelectedLanguages ).


2 Answers

Here is the fix. We need to set UpdateSourceTrigger for the listbox for selectedItem,

<DataTemplate>
   <ListBox DisplayMemberPath="Name" ItemsSource="{Binding Actions}" SelectedItem="{Binding SelectedAction, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</DataTemplate>
like image 92
fhnaseer Avatar answered Sep 26 '22 00:09

fhnaseer


I don't know if it is your case but since you've said that you have cut some information I'll try to answer.

this happen to me when I add a custum template to a ListBox or ListView and that the controls within the ListBoxItem handle the click event themselve.

For example if you have a radio button like this

<ListBox ItemsSource="{Binding List}" SelectedItem="{Binding item}">
  <ListBox.ItemTemplate>
    <DataTemplate>
      <RadioButton Content="{Binding Name}" GroupName="groupName">
    </DataTemplate>
  </ListBox.ItemTemplate>
</ListBox>

The SelectedItem will not be set when you actualy click on the radio button because the radio button will handle the click event and will not bubble it up so the ListBox may change it's selection.

You have to make sure that the ListBox get the event and that the controls in the template react accordingly. in this case you'll have to do something like this.

<ListBox ItemsSource="{Binding List}" SelectedItem="{Binding Item}">
  <ListBox.ItemTemplate>
    <DataTemplate>
      <RadioButton Content="{Binding Name}" IsHitTestVisible="False">
        <RadioButton.Style>
          <Style TargetType="{x:Type RadioButton}">
            <Setter Property="IsChecked" Value="{Binding Path=IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}" />
          </Style>
        </RadioButton.Style>
      </RadioButton>
    </DataTemplate>
  </ListBox.ItemTemplate>
</ListBox>
like image 30
user1098580 Avatar answered Sep 25 '22 00:09

user1098580