Reputation: 13
I am working on the ability to add and delete rows in an observable collection. I have UserControl view with the ListView bound to the ObservableCollection. I have also delete command with is working in the ViewModel but don't update the UI.
This is my code on the ViewModel with is inherit from MvvmLight ViewModelBase class.
public class ProductInfoViewModel : ViewModelBase
{
#region Properties
private ObservableCollection<Product> _productList;
public ObservableCollection<Product> ProductList
{
get { return _productList; }
set
{
_productList = value;
RaisePropertyChanged("ProductList");
}
}
#endregion
#region Constructor
public ProductInfoViewModel()
{
ConnectWebService connect = new ConnectWebService();
string json = connect.getResponse(@"http://localhost:8082/products");
ProductList = JsonConvert.DeserializeObject<ObservableCollection<Product>>(json);
DeleteCommand = new RelayCommand<long>((id) => DeleteCommandHandler(id, ProductList));
}
#endregion
#region Commands
public ICommand DeleteCommand { get; private set; }
#endregion
#region CommandsHandlers
private void DeleteCommandHandler(long id, ObservableCollection<Product> productList)
{
try
{
productList.Remove(productList.Where(i => i.ProductId == id).First());
}
catch (Exception)
{
}
}
This is my code in XAML:
<UserControl.DataContext>
<local:ProductInfoViewModel/>
</UserControl.DataContext>
<Grid>
<Grid Margin="0,50,0,100">
<ListView Margin="5" SelectionChanged="ListView_SelectionChanged" ItemsSource="{Binding ProductList, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Foreground="Black" Background="White" BorderBrush="{x:Null}"
x:Name="ProductList">
<ListView.View>
<GridView>
<GridViewColumn Header="Kod" Width="50" DisplayMemberBinding="{Binding ProductCode}"/>
<GridViewColumn Header="Nazwa" Width="150" DisplayMemberBinding="{Binding ProductName}" />
<GridViewColumn Header="Typ" Width="150" DisplayMemberBinding="{Binding ProductType}" />
<GridViewColumn Header="Opis" Width="300" DisplayMemberBinding="{Binding ProductDescription}" />
<GridViewColumn Header="Dostępność" Width="150" DisplayMemberBinding="{Binding ProductAvability}" />
<GridViewColumn Width="80">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Button Content="Edytuj" Background="Transparent" BorderThickness="0" Foreground="Blue" Width="50" Margin="0" HorizontalAlignment="Center"
Click="Button_Click"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Width="80">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Button Content="Usuń" Background="Transparent" BorderThickness="0" Foreground="Blue" Width="50" Margin="0" HorizontalAlignment="Center"
Click="Delete_Click" Command="{Binding ProductInfoView.DeleteCommand, Mode=OneWay, Source={StaticResource Locator}}" CommandParameter="{Binding ProductId}"
/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
</Grid>
My product class implements INotifyPropertyChanged interface, but I also use Fody.
Right now the view is updating only when I changing a view to another and then go back. I can't figure out what is wrong. I would be grateful for any help!
Upvotes: 1
Views: 1208
Reputation: 169400
You are binding the Command
property of the Button
to the view model returned by your Locator
resource. You should bind it to the same instance that the ListView
is bound to:
<DataTemplate>
<Button Content="Usuń" Background="Transparent" BorderThickness="0" Foreground="Blue" Width="50" Margin="0" HorizontalAlignment="Center"
Click="Delete_Click"
Command="{Binding DataContext.DeleteCommand, RelativeSource={RelativeSource AncestorType=ListView}}"
CommandParameter="{Binding ProductId}"/>
</DataTemplate>
Upvotes: 0
Reputation: 317
When you delete items from the list you do not use your product list setter so RaisePropertyChanged
does not get called. a quick fix would be to add a call to RaisePropertyChanged
after you remove an item:
productList.Remove(productList.Where(i => i.ProductId == id).First());
RaisePropertyChanged("ProductList");
Upvotes: -1