I am using a TabControl with two TabItems. In the first TabItem, I have a list, and in the second TabItem, I have the details. I want that when I save the details in the second TabItem, the new item is added to the list in the first TabItem and ordered in real time.
The new item is added correctly, but it is not sorted by date as it should be, even though I have implemented ICollectionViewLiveShaping. How can I ensure that the new item is automatically sorted by date in the list?
ObservableCollection<UscitaModelView> _ocUscite=new();
// Configura ICollectionView e ICollectionViewLiveShaping
var collectionView = CollectionViewSource.GetDefaultView(_ocUscite) as ICollectionView;
if (collectionView != null)
{
collectionView.SortDescriptions.Add(new SortDescription("Date", ListSortDirection.Descending));
Uscite = collectionView as ICollectionViewLiveShaping;
if (Uscite != null)
{
Uscite.IsLiveSorting = true;
Uscite.IsLiveFiltering = true;
}
}
LoadUscite();
"Uscite" is a ICollectionViewLiveShaping type.
UPDATE
MainViewMOdel
public partial class MainViewModel:ObservableObject
{
public MainViewModel(NavigationService<BaseTabViewModel> ns)
{
Tabbing= ns;
}
[ObservableProperty] NavigationService<BaseTabViewModel> _tabbing;
[ObservableProperty] FatturaFornitoreManager? _fattureFornitori=new();
[ObservableProperty] UsciteManagerViewModel _usciteManager = new();
}
The NavigationService for add or remove tabitem
public partial class NavigationService<T>:ObservableObject
{
[ObservableProperty] ObservableCollection<T> _tabs = new();
[ObservableProperty] T? _selectedTab;
public void AddTab(T tab)
{
if(tab is not null)
{
Tabs.Add(tab);
SelectedTab = tab;
}
}
[RelayCommand]
void RemoveTab(T tab)
{
if (tab is not null)
{
Tabs.Remove(tab);
if (Tabs.Count > 1)
{
SelectedTab = Tabs[Tabs.Count - 1];
}
}
}
}
BaseTabViewModel
public partial class BaseTabViewModel:ObservableObject
{
[ObservableProperty] string? _header;
[ObservableProperty] ViewModelBase? _contentTab;
}
UsciteManagerViewModel
public partial class UsciteManagerViewModel: ObservableObject
{
readonly NavigationService<BaseTabViewModel> _ns;
public UsciteManagerViewModel()
{
_ns = App.Me.ServiceProvider!.GetRequiredService<NavigationService<BaseTabViewModel>>();
}
[RelayCommand(CanExecute = nameof(CanOpenUscite))]
void OpenUscite()
{
UsciteViewModel usc = new();
BaseTabViewModel tab = new();
tab.Header = "Lista uscite";
tab.ContentTab = usc;
_ns.AddTab(tab);
}
private bool CanOpenUscite()
{
var tab = _ns.Tabs.Where(c => c.ContentTab is UsciteViewModel).FirstOrDefault();
if (tab is null) return true;
return false;
}
}
Snippet in MainWindow
<Ribbon>
<RibbonTab>
<RibbonGroup Header="Uscita"
DataContext="{Binding UsciteManager}">
<RibbonButton Label="Movimenti"
ToolTipTitle="Lista dei movimenti"
ToolTipDescription="Apre la lista dei movimenti"
Command="{Binding OpenUsciteCommand}"
Height="18"
VerticalAlignment="Top" />
</RibbonGroup>
</RibbonTab>
</Ribbon>
<TabControl Grid.Row="1"
DataContext="{Binding Tabbing}"
SelectedItem="{Binding SelectedTab,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
ItemsSource="{Binding Tabs}"
ItemContainerStyle="{StaticResource MainTab}"
IsSynchronizedWithCurrentItem="True">
<DataTemplate DataType="{x:Type vm:FattureFornitoriViewModel}">
<views:ucFattureFornitori />
</DataTemplate>
<DataTemplate DataType="{x:Type vm:UsciteViewModel}">
<views:ucUscite />
</DataTemplate>
</TabControl.Resources>
</TabControl>
UsciteViewModel
public partial class UsciteViewModel:ViewModelBase
{
GenericRepository<UscitaModel> _repoUscite;
ObservableCollection<UscitaModelView> _ocUscite;
public UsciteViewModel()
{
_repoUscite = new(Tabella.uscita);
_ocUscite = new();
// Configura ICollectionView e ICollectionViewLiveShaping
var collectionView = CollectionViewSource.GetDefaultView(_ocUscite) as ICollectionView;
if (collectionView != null)
{
collectionView.SortDescriptions.Add(new SortDescription("Data", ListSortDirection.Descending));
Uscite = collectionView as ICollectionViewLiveShaping;
if (Uscite != null)
{
Uscite.LiveSortingProperties.Add("Data");
Uscite.IsLiveSorting = true;
Uscite.IsLiveFiltering = true;
}
}
LoadUscite();
}
[ObservableProperty] ICollectionViewLiveShaping _uscite;
[ObservableProperty] string? _searchText;
[RelayCommand]
async Task OpenUscita(UscitaModelView uscita)
{
if (uscita is null) return;
}
partial void OnSearchTextChanged(string? value)
{
if (_ocUscite is null || _ocUscite.Count == 0) return;
}
async void LoadUscite()
{
var uscitemodel = await _repoUscite.GetAllAsync();
if (uscitemodel is not null)
{
foreach (var uscita in uscitemodel)
{
_ocUscite.Add(new UscitaModelView(uscita));
}
}
}
public void AddUscita(UscitaModel uscita)
{
if (uscita is not null)
{
_ocUscite.Add(new UscitaModelView(uscita));
}
}
}
ViewModel that add new uscitamodelview
public partial class FatturaFornitoreViewModel: FatturaFornitoreModelView
{
public event EventHandler<EventArgs> OnFatturaMovedToUscite;
public FatturaFornitoreViewModel(FatturaFornitore fatturaFornitore) : base(fatturaFornitore)
{
}
[ObservableProperty] FatturaFornitoreToMovement? _fatturaFornitoreToMovement;
[ObservableProperty] bool _isAddDettagliFatturaFornitore;
[ObservableProperty] bool _isSaveAllegati;
[ObservableProperty] bool _isSaveAllegatiEnabled;
partial void OnIsAddDettagliFatturaFornitoreChanged(bool value)
{
if (value)
{
FatturaFornitoreToMovement = new();
FatturaFornitoreToMovement.OnIsSavable += (s, e) =>
{
SaveToUsciteCommand.NotifyCanExecuteChanged();
};
}
else
{
FatturaFornitoreToMovement.OnIsSavable -= (s, e) =>
{
SaveToUsciteCommand.NotifyCanExecuteChanged();
};
FatturaFornitoreToMovement = null;
}
}
[RelayCommand]
async Task VisualizzaFattura()
{
await ((string)Fattura!.Data!).ViewHtmlFromStringXmlAsync(Fattura.NomeFile!);
}
[RelayCommand(CanExecute =nameof(CanOpenAllegato))]
async Task VisualizzaAllegato()
{
var primoFile=Allegati!.First();
await primoFile.Attachment!.ViewFileFromBytesAsync($"{primoFile.NomeAttachment!}.{primoFile.FormatoAttachment}");
}
bool CanOpenAllegato()
{
bool isValid = Allegati is not null && Allegati.Any();
IsSaveAllegatiEnabled = isValid;
return isValid;
}
[RelayCommand(CanExecute =nameof(CanSave))]
async Task SaveToUscite()
{
// Implement logic to save the invoice to the Uscite
UscitaModel model = new();
model.IdUscita = IdFattura;
model.Numero = Numero;
model.Data = Data;
model.Categoria = FatturaFornitoreToMovement?.Categoria!;
model.SubCategoria = FatturaFornitoreToMovement?.SubCategoria;// ?? string.Empty;
model.Fornitore = Fornitore;
model.TipoDocumento = TipoDocumento;
model.DettaglioFornitura =DettaglioFornitura;
model.ImportoTotaleDocumento = ImportoTotaleDocumento;
model.DataScadenza = DataScadenza;
model.DataPagamento = FatturaFornitoreToMovement?.DataPagamento;
model.ModalitaPagamento = FatturaFornitoreToMovement?.ModoPagamento;
model.Destinatario = Destinatario;
model.DataOperazione=FatturaFornitoreToMovement?.ModoPagamento is null ? null : DateTime.Now;
if (FatturaFornitoreToMovement is not null && FatturaFornitoreToMovement.DocumentiPagamento is not null && FatturaFornitoreToMovement.DocumentiPagamento.Count>0)
{
model.Documenti = FatturaFornitoreToMovement.DocumentiPagamento;
}
if (IsSaveAllegati)
{
model.Allegati = Allegati;
}
model.Fattura=Fattura;
GenericRepository<UscitaModel> _repoUscite = new(Tabella.uscita);
if(await _repoUscite.CreateAsync(model))
{
var _repoFattureFornitori = new GenericRepository<FatturaFornitore>(Tabella.fatturafornitore);
await _repoFattureFornitori.DeleteAsync<string>(IdFattura!);
OnFatturaMovedToUscite?.Invoke(this, EventArgs.Empty);
}
FatturaFornitoreToMovement?.CheckExistsAndValidation();
var tabs=App.Me.ServiceProvider!.GetRequiredService<NavigationService<BaseTabViewModel>>().Tabs;
var tab = tabs.FirstOrDefault(t => t.ContentTab is UsciteViewModel);
if (tab is not null)
{
var uscite=tab.ContentTab as UsciteViewModel;
uscite?.AddUscita(model);
}
}
bool CanSave()=>FatturaFornitoreToMovement?.Categoria.CheckString() != null;
}
I hope it is clear enough.
Thanks
I solved it by adding the following to the resources of ucUscite and setting the type of the Uscite property to ObservableCollection<UscitaModelView>:
<UserControl.Resources>
<CollectionViewSource x:Key="UsciteList" Source="{Binding Uscite}">
<CollectionViewSource.SortDescriptions>
<scm:SortDescription PropertyName="Data"
Direction="Descending" />
<scm:SortDescription PropertyName="Fornitore" />
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
</UserControl.Resources>
and
<DataGrid ItemSource={Binding Source={StaticResource UsciteList}}>
Thanks