Domanda

Sto associando un CollectionViewSource a un ListView per raggruppare gli elementi. Funziona alla grande, tranne quando aggiorno ObservableCollection su cui si basa il CollectionViewSource . Se aggiorno un valore di un oggetto nella raccolta, l'interfaccia utente non viene mai aggiornata. Ecco un esempio:

<ListView x:Name="MyListView" Margin="0,0,0,65">
    <ListView.GroupStyle>
        <GroupStyle>
            <GroupStyle.ContainerStyle>
                <Style TargetType="{x:Type GroupItem}">
                    <Setter Property="Margin" Value="0,0,0,5"/>
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type GroupItem}">
                                <Expander IsExpanded="true" BorderBrush="#FFA4B97F" BorderThickness="0,0,0,1">
                                    <Expander.Header>
                                        <DockPanel>
                                            <TextBlock FontWeight="Bold" Text="{Binding Name}" Margin="5,0,0,0" Width="80"/>
                                            <TextBlock FontWeight="Bold" Width="60" TextAlignment="Center" Margin="16,0,0,0" Text="{Binding Items, Converter={StaticResource Converter2}}" />
                                        </DockPanel>
                                    </Expander.Header>
                                    <ItemsPresenter />
                                </Expander>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </GroupStyle.ContainerStyle>
        </GroupStyle>
    </ListView.GroupStyle>
    <ListView.View>
        <GridView>
            <GridViewColumn Width="300" Header="Amount" >
                <GridViewColumn.CellTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Amount}" Margin="80,0,0,0"/>
                    </DataTemplate>
                 </GridViewColumn.CellTemplate>
            </GridViewColumn>
        </GridView>
    </ListView.View>
</ListView>

Noterai che chiama un convertitore nel gruppo e gli dà la raccolta degli oggetti. In questo modo il convertitore può calcolare la media delle righe e restituire quel risultato:

public class AverageConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        IEnumerable<object> rows = (IEnumerable<object>) value;
        double average = rows.Average(a => ((DisplayRow) a).Amount);
        return average;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Nel codice dietro aggiungo le righe e creo CollectionViewSource :

osservabile in privato ObservableCollection displayRows = new ObservableCollection ();

public Window1()
{
    InitializeComponent();

    displayRows.Add(new DisplayRow { Title = "Sales", Amount=16} );
    displayRows.Add(new DisplayRow { Title = "Marketing", Amount=14} );
    displayRows.Add(new DisplayRow { Title = "Technology", Amount=13} );
    displayRows.Add(new DisplayRow { Title = "Sales", Amount=11} );
    displayRows.Add(new DisplayRow { Title = "Marketing", Amount=13} );
    displayRows.Add(new DisplayRow { Title = "Technology", Amount=12} );
    CollectionViewSource viewSource = new CollectionViewSource { Source = displayRows };
    viewSource.GroupDescriptions.Add(new PropertyGroupDescription("Title"));
    MyListView.ItemsSource = viewSource.View;
}

L'oggetto DisplayRow implementa INotifyPropertyChanged ed è solo una classe semplice.

Tutto funziona bene e il display è come voglio, ma se cambio un valore in ObservableCollection l'interfaccia utente non cambia.

Se aggiungo un elemento alla raccolta posso vederlo apparire sullo schermo ma il convertitore non viene mai chiamato per ricalcolare la media. Qualche idea?

È stato utile?

Soluzione

Ho trovato un modo per aggirare questo problema.

private CollectionViewSource _viewSource;

private void ModifyData()
{
    // Modify some data

    // This will cause the ListView to refresh its data and update the UI
    // and also cause the converter to be called to reformat the data.
    _viewSource.View.Refresh();
}

Spero che sia d'aiuto.

Altri suggerimenti

Senza aggiornare l'intera vista, questo può ancora essere gestito, l'ho implementato.

La creazione di banche dati all'interno di CollectionView consentirà le notifiche di modifica per i gruppi.

Guarda http: //stumblingaroundinwpf.blogspot .com / 2009/11 / edificio-intelligente-WPF-CollectionView-uno.html

Se l'origine dati è ObservableCollection, la vista verrà aggiornata ogni volta che la raccolta viene modificata, ovvero quando vi sono elementi aggiunti o rimossi da essa. Se vuoi che la vista venga aggiornata quando i dati sottostanti vengono modificati, quella classe deve implementare l'interfaccia INotifyPropertyChanged.

Nel tuo caso la classe DisplayRow deve implementare INotifyPropertyChanged e displayRows dovrebbe essere un ObservableCollection.

Questo è il modo ufficiale per farlo, da quello che ho capito. Potrei sbagliarmi.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top