【问题标题】:Observablecollection.RemoveAt(item) doesn't refresh UIObservablecollection.RemoveAt(item) 不刷新 UI
【发布时间】:2014-12-15 11:38:28
【问题描述】:

我有一个 ObservableCollection<MyType>,其中 MyType 使用 Fody 实现 INotifyPropertyChanged

这个集合被绑定到我的用户界面上

<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); }
 }

还有这个每次删除一行的命令

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);
    }
}

我的问题是当从集合 id 中删除一个项目时,它不会刷新 UI。

如何强制 de UI 刷新?

【问题讨论】:

  • 感谢您的建议,但添加它是为了强制刷新 UI。
  • 从绑定到属性的集合中删除项目不会调用设置器,其中可能会触发PropertyChanged,如果您想在添加项目时通知CollectionChanged事件从集合中删除。
  • DetellePresupuesto 是实现 INotifyCollectionChanged 的​​集合吗?如果不是,它应该是(像 ObservableCollection)。
  • 但它是一个 ObservableCollection
  • 请问RemoveAt的原因?你不能简单地做 DetellePresupuesto.Remove(item);??

标签: c# wpf


【解决方案1】:

您没有绑定到 UI 中的 DetallePresupuesto。您正在绑定:

return new ObservableCollection<MyType>();

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

要更新 UI,您需要让属性返回要从中删除的列表,即 DetallePresupuesto。这意味着 getter 应该看起来像这样。

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

        return _DetallePresupuesto;
    }
}

另外,尽量避免为您的集合设置 setter。

【讨论】:

  • 不错的收获。更短:返回 _DetellePresupuesto ?? (_DetallePresupuesto = new ObservableCollection());
  • @nkoniishvt 这是一个偏好问题..I'd rather have it in the constructor 因为绑定是在加载时创建的(即延迟初始化不会很懒很长时间)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-18
  • 1970-01-01
  • 2013-10-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多