0

I have an ObservableCollection<MyType>, where MyType implements INotifyPropertyChanged using Fody.

This collection was binded to my ui as this

<Grid x:Name="DetallePresupuesto" Grid.Row="2">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <TextBlock Text="{x:Static resources:Labels.SALUD_DetallePresupuesto}" Background="Bisque" TextAlignment="Center"/>
    <DataGrid 
        x:Name="DetallePresupuestoGrid" 
        Grid.Row="1" 
        Grid.ColumnSpan="1" 
        AutoGenerateColumns="False" 
        Style="{DynamicResource ParadigmaNDataGrid}" 
        ItemsSource="{Binding Path=DetallePresupuesto,UpdateSourceTrigger=PropertyChanged}">
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="SelectionChanged">
                <cmd:EventToCommand Command="{Binding ItemSelectionChangedCommand}" CommandParameter="{Binding ElementName=DetallePresupuestoGrid, Path=SelectedItem}"/>
            </i:EventTrigger>
            <i:EventTrigger EventName="AddingNewItem">
                <cmd:EventToCommand Command="{Binding InsertItemCommand}" PassEventArgsToCommand="True"/>
            </i:EventTrigger>
        </i:Interaction.Triggers>
        <DataGrid.Columns>
            <DataGridTemplateColumn Header="{x:Static resources:Labels.GENERAL_Item}" Width="10*" ClipboardContentBinding="{x:Null}">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Merlin_ConceptosFacturacion.StrDescripcionConcepto}"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
                <DataGridTemplateColumn.CellEditingTemplate>
                    <DataTemplate>
                        <controls:Search SearchParms="{Binding ElementName=EstaVentana,Path=DataContext.BusqItems}"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellEditingTemplate>
            </DataGridTemplateColumn>
            <DataGridTextColumn Header="{x:Static resources:Labels.GENERAL_Cantidad}" Width="2*" Binding="{Binding Path=NumCantidad}" ClipboardContentBinding="{x:Null}"/>
            <DataGridTextColumn Header="{x:Static resources:Labels.GENERAL_ValorUnitario}" Width="2.5*" Binding="{Binding Path=NumValorFacturacionDigitado}" ClipboardContentBinding="{x:Null}"/>
            <DataGridTextColumn Header="{x:Static resources:Labels.GENERAL_ValorTotal}" Width="2.5*" Binding="{Binding Path=NumValor}" ClipboardContentBinding="{x:Null}"/>
            <DataGridTemplateColumn Width="70" Header="{x:Static resources:Labels.GENERAL_BorrarItem}" HeaderStyle="{StaticResource ResourceKey=ParadigmaNDataGridHeaderStyle}">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <Button Style="{StaticResource InLineDeleteButton}" Command="{Binding Path=DataContext.DeleteCommand, ElementName=EstaVentana}" CommandParameter="{Binding ElementName=DetallePresupuestoGrid,Path=SelectedItem}" Visibility="{Binding Merlin_ConceptosFacturacion.NumIdConcepto,Converter={cnv:decimalToVisibilityConverter}}"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
    </DataGrid>
</Grid>


private ObservableCollection<MyType> _DetallePresupuesto;
public ObservableCollection<MyType> DetallePresupuesto
{
    get {
        if (_DocumentoPresupuesto == null)
            return new ObservableCollection<MyType>();
        else
            return new ObservableCollection<MyType>(_DocumentoPresupuesto.Parent.MyType);
    }
    set { SetProperty(ref _DetallePresupuesto, value); }
 }

And this command that deletes one row each time

public void ExecuteDelete(object p)
{
    try
    {
        bool borro = false;
        MyType det = (MyType)p;
        MyType item = DetallePresupuesto.Where(x => x.NumIdTransaccion == det.NumIdTransaccion).FirstOrDefault();
        if (item != null)
        {
            DetallePresupuesto.RemoveAt(DetallePresupuesto.IndexOf(item));
            db.SetEntityState(det, EntityState.Deleted);
            db.SaveEntity(det);
        }
    }
    catch (Exception e)
    {
        ReportarInconsistencia(e.Message);
    }
}

My problem is when delete an item from the collection id does it but it doesn't refresh the UI.

How can I Do to force de UI refresh ?

default
  • 11,485
  • 9
  • 66
  • 102
Juan Pablo Gomez
  • 5,203
  • 11
  • 55
  • 101
  • Tks for your suggestion b ut it was added trying to force the UI refresh. – Juan Pablo Gomez Dec 15 '14 at 11:41
  • Removing an item froma collection bound to a property does not call the setter, where presumably to fire `PropertyChanged`, wire something up tom the `CollectionChanged` event if you want to notify when items are added/removed form the collection. – Ben Robinson Dec 15 '14 at 11:44
  • Is DetallePresupuesto a collection implementing INotifyCollectionChanged? If not, it should be (like an ObservableCollection). – nkoniishvt Dec 15 '14 at 11:44
  • But It is an ObservableCollection – Juan Pablo Gomez Dec 15 '14 at 11:50
  • Can I ask the reason for RemoveAt? Can you not simply do DetallePresupuesto.Remove(item);?? – Krishna Dec 15 '14 at 11:50
  • RemoveAt because Remove doesn't work to – Juan Pablo Gomez Dec 15 '14 at 11:52
  • @JuanPabloGomez did you check if the ObservableCollection is notifying of CollectionChanged with the Action equals to System.Collections.Specialized.NotifyCollectionChangedAction.Remove? – nkoniishvt Dec 15 '14 at 12:00
  • @Krishna this looks like elements bound to something from EntityFramework, thus they might be detached objects and he needs to find the connected object (via the ID). Just a hunch though.. – default Dec 15 '14 at 12:01
  • If you use MVVM architecture, you don't need to use the Remove method.You only need to handle the CollectionChanged in ViewModel. – M.G.E Dec 15 '14 at 12:03
  • @TommyMoore Yes I'm using MVVM but doesn't understand what exactly be handled. Sorry for my ignorance. – Juan Pablo Gomez Dec 15 '14 at 12:05
  • You need to define a ObservableCollection in ViewModel then bind it to your grid's DataContext property. – M.G.E Dec 15 '14 at 12:11
  • @TommyMoore he has an ObservableCollection in his viewmodel. He is binding to his DataContext. Please read the question and comments. There are plenty regarding OC right now. – default Dec 15 '14 at 12:12
  • @TommyMoore There's nothing in MVVM which says that you can't modify a Property or a Collection in the ViewModel. This is why TwoWay bindings exists. His RemoveAt use is absolutely correct. – nkoniishvt Dec 15 '14 at 12:13
  • You can always use Remove property but in this scenario it doesn't need to use that and by the way i think you refer the wrong Name. the dataGrid's name is DetallePresupuestoGrid not DetallePresupuesto. – M.G.E Dec 15 '14 at 12:17

1 Answers1

3

You're not binding to DetallePresupuesto in the UI. You are binding to either:

return new ObservableCollection<MyType>();

or

return new ObservableCollection<MyType>(_DocumentoPresupuesto.Parent.MyType);

For the UI to be updated you need to let the property return the list that you are removing from, i.e. the DetallePresupuesto. That means the getter should look something like this.

public ObservableCollection<MyType> DetallePresupuesto
{
    get {
        if (_DetallePresupuesto == null)
            _DetallePresupuesto = new ObservableCollection<MyType>(); //populate here

        return _DetallePresupuesto;
    }
}

Also, try to avoid setters for your collections.

default
  • 11,485
  • 9
  • 66
  • 102
  • Nice catch. Shorter: return _DetallePresupuesto ?? (_DetallePresupuesto = new ObservableCollection()); – nkoniishvt Dec 15 '14 at 12:08
  • @nkoniishvt it's a matter of preference.. [I'd rather have it in the constructor](http://stackoverflow.com/a/17183876/238902) since the binding is created at load anyway (i.e. the lazy initalization won't be very lazy for long). – default Dec 15 '14 at 12:15