0

I am working on an App, in which I am able to attach attachments like images and audio to a profile and display those attachments in CreateAndUpdateRiskProfileView. I can add attachments with the AddAttachmentModal. When I choose an attachment there it will be automatically displayed in the CreateAndUpdatetRiskProfileView. Now I also want to be able to delete attachments permanently from the database. This is possible when I longpress on an attachment in the AddAttachmentModal and select delete. Now this works and the attachment is not being displayed in the AddAttachmentModal and if I go to another profile which used this attachment, the attachment is also gone. However, in the CreateAndUpdateRiskProfileView of the Profile where I just deleted an attachment this attachment is still there and will remain there until I close the App and build again. I want the deleted attachment to not show anymore imidiatly, but I don't know how I can make this happen. I would appreciate the help!

This is the CreateAndUpdateRiskProfileView :

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:controls="clr-namespace:SiRiAs.Controls"
             xmlns:flowlayout="clr-namespace:SiRiAs.Controls.FlowLayout"
             xmlns:behaviours="clr-namespace:SiRiAs.Behaviors"
             xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
             xmlns:convertes="clr-namespace:SiRiAs.Lib.Converters;assembly=SiRiAs.Lib"
             xmlns:selectors="clr-namespace:SiRiAs.Lib.TemplateSelectors;assembly=SiRiAs.Lib"
             xmlns:viewmodel="clr-namespace:SiRiAs.Lib.ViewModels;assembly=SiRiAs.Lib"
             xmlns:models="clr-namespace:SiRiAs.Lib.Models;assembly=SiRiAs.Lib"
            
             x:Class="SiRiAs.Views.CreateAndUpdateRiskProfileView"
             x:DataType="viewmodel:CreateAndUpdateRiskProfileViewModel"
             Shell.NavBarIsVisible="False">

    <ContentPage.Resources>
        <ResourceDictionary>
            <convertes:LocationToStringConverter x:Key="LocationToStringConverter"
                                                 DefaultConvertReturnValue="0°0'0''N 0°0'0''W"/>

            <DataTemplate x:Key="ImageAttachmentView"
                          x:DataType="models:Attachment">
                <controls:LongPressImageButton Style="{StaticResource PreviewImageButtonStyle}"
                             Aspect="AspectFill"
                             HeightRequest="70" 
                             WidthRequest="70"
                             Source="{Binding Link}"
                             LongPressCommand="{Binding Source={RelativeSource AncestorType={x:Type viewmodel:CreateAndUpdateRiskProfileViewModel}}, Path=ShowDeleteOptionCommand}"
                             LongPressCommandParameter="{Binding .}"
                            />
            </DataTemplate>

            <DataTemplate x:Key="AudioAttachmentView"
                          x:DataType="models:Attachment">
                <controls:LongPressButton Style="{StaticResource PreviewButtonStyle}"
                        Text="{Binding Name}"
                        HeightRequest="70"
                        WidthRequest="70" 
                        LongPressCommand="{Binding Source={RelativeSource AncestorType={x:Type viewmodel:CreateAndUpdateRiskProfileViewModel}}, Path=ShowDeleteOptionCommand}"
                        LongPressCommandParameter="{Binding .}"/>
            </DataTemplate>

This is the CreateAndUpdateProfileView.xaml.cs

using SiRiAs.Lib.ViewModels;

namespace SiRiAs.Views;

public partial class CreateAndUpdateRiskProfileView : ContentPage {

    private readonly CreateAndUpdateRiskProfileViewModel _viewModel;

    public CreateAndUpdateRiskProfileView(CreateAndUpdateRiskProfileViewModel createAndUpdateRiskProfileViewModel) {
        InitializeComponent();
        _viewModel = createAndUpdateRiskProfileViewModel;
        BindingContext = createAndUpdateRiskProfileViewModel;
    }

    protected override bool OnBackButtonPressed() {
        if(_viewModel.ReturnOrPopupCommand.CanExecute(null)) {
            _viewModel.ReturnOrPopupCommand.Execute(null);
        }
        return true;
    }
}

This is the CreateAndUpdateRiskProfileViewModel:

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using SiRiAs.Lib.Helpers;
using SiRiAs.Lib.Models;
using SiRiAs.Lib.Repositories;
using SiRiAs.Lib.Services;
using System.Collections.ObjectModel;
using System.ComponentModel;

namespace SiRiAs.Lib.ViewModels {

    [QueryProperty(nameof(Intent), nameof(Intent))]
    [QueryProperty(nameof(Model), nameof(Model))]
    [QueryProperty(nameof(ActivityId), nameof(ActivityId))]
    public partial class CreateAndUpdateRiskProfileViewModel : ObservableObject {

        private readonly IUnitOfWork _unitOfWork;
        private readonly IPopupProvider _popupProvider;

        private bool isModelDirty;

        public Guid ActivityId { get; set; }      
        
        [ObservableProperty]
        private Intent intent = Intent.Create;

        [ObservableProperty]
        private RiskProfile model = new();

      
        [ObservableProperty]
        private ObservableCollection<Attachment> attachments = new();


        //...

        public CreateAndUpdateRiskProfileViewModel(IUnitOfWork unitOfWork, IPopupProvider popupProvider) {
            _unitOfWork = unitOfWork;
            _popupProvider = popupProvider;
            PopulateRiskCategories();
        }

        /// <summary>
        /// Populate fields if model is loaded from database
        /// </summary>
        /// <param name="value">model</param>
        partial void OnModelChanged(RiskProfile value) {
            if (value is not null) {
                CreationTimeStamp = Model.CreationDate;
                SelectedRiskCategory = AvailableRiskCategories.FirstOrDefault(riskCategory => riskCategory.Id == Model.RiskCategory?.Id);
                SelectedRiskFeature = AvailableRiskFeatures.FirstOrDefault(riskFeature => riskFeature.Id == Model.RiskFeature?.Id);
                DangerLevel = Model.DangerLevel;
                Description = Model.Description;
                Measures = Model.Measures;
                Location = Model.Location;
                Attachments = new ObservableCollection<Attachment>(model.Attachments);
                isModelDirty = false;
            }
        }

        /// <summary>
        /// Add model to database
        /// </summary>
        [RelayCommand]
        public async void CreateOrUpdate() {
            CommitChanges();
            if (Intent == Intent.Create) {
                Model.ActivityId = ActivityId;
                Model.CreationDate = Model.LastChangeDate = CreationTimeStamp;
                await _unitOfWork.RiskProfiles.Add(Model);
                await _unitOfWork.Save();
                Model.Attachments = Attachments.ToList();
            } else if (Intent == Intent.Update) {
                Model.LastChangeDate = DateTime.Now;
                Model.Attachments = Attachments.ToList();
                _unitOfWork.RiskProfiles.Update(Model);
            }
            await _unitOfWork.Save();
            NavigateBack();
        }


        [RelayCommand]
        public async void AddAttachment() {
            var selectedAttachment = await _popupProvider.ShowAddAttachmentPopup();
            if (selectedAttachment is not null && !AttachmentAlreadyAttached(selectedAttachment)) {
                Attachments.Add(selectedAttachment);
                isModelDirty = true;
            } 
        }

        [RelayCommand]
        public async void ShowDeleteOption(Attachment attachment) {
            var result = await _popupProvider.ShowDeleteAttachmentModal();
            if(result.Equals(MoreOptionsPopupResult.Delete)) {
                var deleteResult = await _popupProvider.ShowDeletePopup();
                if(deleteResult.Equals(DeleteDialogResult.Delete)) {
                    Attachments.Remove(attachment);
                    isModelDirty = true;
                }
            }
        }

      //...

This the the AddAttachmentModal which gets via AddAttachment():

modals:BaseModalPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:modals="clr-namespace:SiRiAs.Views.Modals"
             xmlns:controls="clr-namespace:SiRiAs.Controls"
             xmlns:viewmodel="clr-namespace:SiRiAs.Lib.ViewModels;assembly=SiRiAs.Lib" 
             xmlns:behaviors="clr-namespace:SiRiAs.Behaviors" 
             xmlns:selectors="clr-namespace:SiRiAs.Lib.TemplateSelectors;assembly=SiRiAs.Lib"
             xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
             xmlns:models="clr-namespace:SiRiAs.Lib.Models;assembly=SiRiAs.Lib"
             x:Class="SiRiAs.Views.Modals.AddAttachmentModal"
             x:DataType="viewmodel:AddAttachmentModalViewModel"
             xmlns:convertes="clr-namespace:SiRiAs.Lib.Converters;assembly=SiRiAs.Lib"
             Title="AddAttachmentPopup">

    <ContentPage.Resources>
        <DataTemplate x:Key="ImageAttachmentView" x:DataType="models:Attachment">
            <controls:LongPressImageButton Style="{StaticResource PreviewImageButtonStyle}" 
                         Aspect="AspectFill"
                         Source="{Binding Link}" 
                         Command="{Binding Source={RelativeSource AncestorType={x:Type viewmodel:AddAttachmentModalViewModel}}, Path=SelectedCommand}"
                         CommandParameter="{Binding .}"
                         LongPressCommand="{Binding Source={RelativeSource AncestorType={x:Type viewmodel:AddAttachmentModalViewModel}}, Path=ShowDeleteOptionCommand}"
                         LongPressCommandParameter="{Binding .}"
                                           
                         />
        </DataTemplate>
        
        <DataTemplate x:Key="AudioAttachmentView" x:DataType="models:Attachment">
            <controls:LongPressButton Style="{StaticResource PreviewButtonStyle}" 
                    Text="{Binding Name}"
                    Command="{Binding Source={RelativeSource AncestorType={x:Type viewmodel:AddAttachmentModalViewModel}}, Path=SelectedCommand}"
                    CommandParameter="{Binding .}"
                    LongPressCommand="{Binding Source={RelativeSource AncestorType={x:Type viewmodel:AddAttachmentModalViewModel}}, Path=ShowDeleteOptionCommand}"
                    LongPressCommandParameter="{Binding .}"
                    />
        </DataTemplate>

//...

The AddAttachmentModalViewModel:

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using SiRiAs.Lib.Models;
using SiRiAs.Lib.Repositories;
using System.Collections.ObjectModel;
using System.Diagnostics;
using SiRiAs.Lib.Services;
using SiRiAs.Lib.Helpers;

namespace SiRiAs.Lib.ViewModels {
    public partial class AddAttachmentModalViewModel : ObservableObject {
        [ObservableProperty]
        private ObservableCollection<Attachment> attachments;

        private readonly IUnitOfWork _unitOfWork;
        private readonly IPopupProvider _popupProvider;
//...

        public AddAttachmentModalViewModel(IUnitOfWork unitOfWork, IPopupProvider popupProvider, IAudioRecorder audioRecorder) {
            _unitOfWork = unitOfWork;
            _popupProvider = popupProvider;
            _audioRecorder = audioRecorder;
            OnSelectedAttachmentTypeChanged(SelectedAttachmentType);
        }

        
        [RelayCommand]
        public async void ShowDeleteOption(Attachment attachment) {
            var result = await _popupProvider.ShowDeleteAttachmentPopup();
            if(result.Equals(DeleteDialogResult.Delete)) {
            var deleteResult = await _popupProvider.ShowDeletePopup();
            if(deleteResult.Equals(DeleteDialogResult.Delete)) {
                _unitOfWork.Attachments.Remove(attachment); 
                    await _unitOfWork.Save();
                    Attachments.Remove(attachment);
                foreach(RiskProfile riskProfile in await _unitOfWork.RiskProfiles.GetAll()){
                    if(riskProfile.Attachments.Contains(attachment)) {
                        riskProfile.Attachments.Remove(attachment);
                    }

                }
              }

//...
              
    }
}

0 Answers0