最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c# - MAUI UI not refreshing after successfully deleting file (works for folders) - Stack Overflow

programmeradmin2浏览0评论

When I delete a file, it successfully deletes from the collection, but does not refresh in the ui unless I either exit out of the page or force a page reload in the button function. Deleting folders and renaming the file works fine though.

model:

 public class FileItem
 {
     public string Name { get; set; }
     public string Path { get; set; }
     public bool IsFolder { get; set; }
     public ObservableCollection<FileItem> Items { get; set; } // For nested items in folders
 }

fileExplorer class (handles folder creation, renaming and delete.):

public partial class FileExplorer : ContentPage
{
    public ObservableCollection<FileItem> FileItems { get; set; }

    private readonly string _myReSEEptImagesFolder = Path.Combine(FileSystem.AppDataDirectory, "My ReSEEpt Images");

    public FileExplorer()
    {
        InitializeComponent();

        //Main collection object of all files
        FileItems = new ObservableCollection<FileItem>();
        BindingContext = this;

        InitializeAppDirectory();
        LoadFilesAndFolders();
    }

    private void InitializeAppDirectory()
    {
        if (!Directory.Exists(_myReSEEptImagesFolder))
        {
            Directory.CreateDirectory(_myReSEEptImagesFolder);
        }
    }

    private void LoadFilesAndFolders()
    {
        if (Directory.Exists(_myReSEEptImagesFolder))
        {
            //Grab primary direcotory
            var items = Directory.GetFileSystemEntries(_myReSEEptImagesFolder);
            foreach (var item in items)
            {
                var fileItem = new FileItem
                {
                    Name = Path.GetFileName(item),
                    Path = item,
                    IsFolder = Directory.Exists(item),
                    Items = new ObservableCollection<FileItem>()
                };

                // Load files inside folders
                if (fileItem.IsFolder)
                {
                    var subItems = Directory.GetFileSystemEntries(item);
                    foreach (var subItem in subItems)
                    {
                        fileItem.Items.Add(new FileItem
                        {
                            Name = Path.GetFileName(subItem),
                            Path = subItem,
                            IsFolder = Directory.Exists(subItem)
                        });
                    }
                }

                FileItems.Add(fileItem);
            }
        }
    }

    private async void DeleteItemClicked(object sender, EventArgs e)
    {
        var button = sender as Button;
        var fileItem = button?.BindingContext as FileItem;

        if (fileItem != null)
        {
            bool isConfirmed = await DisplayAlert("Delete", $"Are you sure you want to delete {fileItem.Name}?", "Yes", "No");

            if (isConfirmed)
            {
                try
                {
                    // Delete the file or folder
                    if (File.Exists(fileItem.Path))
                    {
                        File.Delete(fileItem.Path);
                    }
                    else if (Directory.Exists(fileItem.Path))
                    {
                        Directory.Delete(fileItem.Path, true);
                    }

                    // Remove the item from the collection
                    FileItems.Remove(fileItem);

                    // No need to create a new ObservableCollection; just update the existing collection
                    FileCollectionView.ItemsSource = null;
                    FileCollectionView.ItemsSource = FileItems;

                }
                catch (Exception ex)
                {
                    await DisplayAlert("Error", $"Failed to delete {fileItem.Name}: {ex.Message}", "OK");
                }
            }
        }
    }

}

XAML for fileExplorer:

<CollectionView x:Name="FileCollectionView" 
            ItemsSource="{Binding FileItems}" 
            SelectionMode="Single"
            SelectedItem="{Binding SelectedItem, Mode=TwoWay}">
<CollectionView.ItemTemplate>
    <DataTemplate>
        <StackLayout Padding="10">
            <!-- Folder/File Name -->
            <Label Text="{Binding Name}" FontSize="Medium" VerticalOptions="Center" />

            <!-- Buttons for actions (Rename, Delete) for folders -->
            <StackLayout Orientation="Horizontal" HorizontalOptions="End">
                <Button Text="Rename" Clicked="RenameItemClicked" />
                <Button Text="Delete" Clicked="DeleteItemClicked" />
            </StackLayout>

            <!-- Nested CollectionView for files inside folders -->
            <CollectionView IsVisible="{Binding IsFolder}" 
                            ItemsSource="{Binding Items}" 
                            SelectionMode="None">
                <CollectionView.ItemTemplate>
                    <DataTemplate>
                        <StackLayout Padding="10">
                            <!-- File Name -->
                            <Label Text="{Binding Name}" VerticalOptions="Center" />

                            <!-- Buttons for actions (Rename, Delete) for files -->
                            <StackLayout Orientation="Horizontal" HorizontalOptions="End">
                                <!--<Button Text="Rename" Clicked="RenameItemClicked" />
                                <Button Text="Delete" Clicked="DeleteItemClicked" />-->
                            </StackLayout>
                        </StackLayout>
                    </DataTemplate>
                </CollectionView.ItemTemplate>
            </CollectionView>
        </StackLayout>
    </DataTemplate>
</CollectionView.ItemTemplate>

When I delete a file, it successfully deletes from the collection, but does not refresh in the ui unless I either exit out of the page or force a page reload in the button function. Deleting folders and renaming the file works fine though.

model:

 public class FileItem
 {
     public string Name { get; set; }
     public string Path { get; set; }
     public bool IsFolder { get; set; }
     public ObservableCollection<FileItem> Items { get; set; } // For nested items in folders
 }

fileExplorer class (handles folder creation, renaming and delete.):

public partial class FileExplorer : ContentPage
{
    public ObservableCollection<FileItem> FileItems { get; set; }

    private readonly string _myReSEEptImagesFolder = Path.Combine(FileSystem.AppDataDirectory, "My ReSEEpt Images");

    public FileExplorer()
    {
        InitializeComponent();

        //Main collection object of all files
        FileItems = new ObservableCollection<FileItem>();
        BindingContext = this;

        InitializeAppDirectory();
        LoadFilesAndFolders();
    }

    private void InitializeAppDirectory()
    {
        if (!Directory.Exists(_myReSEEptImagesFolder))
        {
            Directory.CreateDirectory(_myReSEEptImagesFolder);
        }
    }

    private void LoadFilesAndFolders()
    {
        if (Directory.Exists(_myReSEEptImagesFolder))
        {
            //Grab primary direcotory
            var items = Directory.GetFileSystemEntries(_myReSEEptImagesFolder);
            foreach (var item in items)
            {
                var fileItem = new FileItem
                {
                    Name = Path.GetFileName(item),
                    Path = item,
                    IsFolder = Directory.Exists(item),
                    Items = new ObservableCollection<FileItem>()
                };

                // Load files inside folders
                if (fileItem.IsFolder)
                {
                    var subItems = Directory.GetFileSystemEntries(item);
                    foreach (var subItem in subItems)
                    {
                        fileItem.Items.Add(new FileItem
                        {
                            Name = Path.GetFileName(subItem),
                            Path = subItem,
                            IsFolder = Directory.Exists(subItem)
                        });
                    }
                }

                FileItems.Add(fileItem);
            }
        }
    }

    private async void DeleteItemClicked(object sender, EventArgs e)
    {
        var button = sender as Button;
        var fileItem = button?.BindingContext as FileItem;

        if (fileItem != null)
        {
            bool isConfirmed = await DisplayAlert("Delete", $"Are you sure you want to delete {fileItem.Name}?", "Yes", "No");

            if (isConfirmed)
            {
                try
                {
                    // Delete the file or folder
                    if (File.Exists(fileItem.Path))
                    {
                        File.Delete(fileItem.Path);
                    }
                    else if (Directory.Exists(fileItem.Path))
                    {
                        Directory.Delete(fileItem.Path, true);
                    }

                    // Remove the item from the collection
                    FileItems.Remove(fileItem);

                    // No need to create a new ObservableCollection; just update the existing collection
                    FileCollectionView.ItemsSource = null;
                    FileCollectionView.ItemsSource = FileItems;

                }
                catch (Exception ex)
                {
                    await DisplayAlert("Error", $"Failed to delete {fileItem.Name}: {ex.Message}", "OK");
                }
            }
        }
    }

}

XAML for fileExplorer:

<CollectionView x:Name="FileCollectionView" 
            ItemsSource="{Binding FileItems}" 
            SelectionMode="Single"
            SelectedItem="{Binding SelectedItem, Mode=TwoWay}">
<CollectionView.ItemTemplate>
    <DataTemplate>
        <StackLayout Padding="10">
            <!-- Folder/File Name -->
            <Label Text="{Binding Name}" FontSize="Medium" VerticalOptions="Center" />

            <!-- Buttons for actions (Rename, Delete) for folders -->
            <StackLayout Orientation="Horizontal" HorizontalOptions="End">
                <Button Text="Rename" Clicked="RenameItemClicked" />
                <Button Text="Delete" Clicked="DeleteItemClicked" />
            </StackLayout>

            <!-- Nested CollectionView for files inside folders -->
            <CollectionView IsVisible="{Binding IsFolder}" 
                            ItemsSource="{Binding Items}" 
                            SelectionMode="None">
                <CollectionView.ItemTemplate>
                    <DataTemplate>
                        <StackLayout Padding="10">
                            <!-- File Name -->
                            <Label Text="{Binding Name}" VerticalOptions="Center" />

                            <!-- Buttons for actions (Rename, Delete) for files -->
                            <StackLayout Orientation="Horizontal" HorizontalOptions="End">
                                <!--<Button Text="Rename" Clicked="RenameItemClicked" />
                                <Button Text="Delete" Clicked="DeleteItemClicked" />-->
                            </StackLayout>
                        </StackLayout>
                    </DataTemplate>
                </CollectionView.ItemTemplate>
            </CollectionView>
        </StackLayout>
    </DataTemplate>
</CollectionView.ItemTemplate>
Share Improve this question edited Mar 14 at 12:53 voods asked Mar 13 at 6:58 voodsvoods 453 bronze badges 5
  • Please provide more context. How is FileItems defined and why are you updating the ItemsSource of the CollectionView manually? How did you set up the binding in XAML? Please provide a minimal reproducible example – Julian Commented Mar 13 at 8:37
  • For ListView to be updated when FileItems members change, FileItems "should be an IEnumerable collection that sends property change notifications, such as ObservableCollection", according to MAUI documentation (learn.microsoft/en-us/dotnet/maui/user-interface/controls/…). Is a such collection in your case? – rentoulis Commented Mar 13 at 10:22
  • @rentoulis It seems like ObservableCollection is already used, which should be sufficient when it comes to removing items. Of course, other property changes won't get propagated, but we need to see more code to see what could be happening. – Julian Commented Mar 13 at 13:03
  • 1 @Julian We do not know for sure the type of FileItems, I think. But I agree that more code will be more helpful :-) – rentoulis Commented Mar 13 at 16:43
  • the types of files being saved are jpg right now if that helps at all. I edited the code to include more. There is a rename and folder create function too but they work fine. – voods Commented Mar 14 at 12:51
Add a comment  | 

1 Answer 1

Reset to default 0

I have made a little test project to find the problem with your solution and my conclusion is that the line:

FileItems.Remove(fileItem);

is problematic, because fileItem is not in FileItems, in the case of a file. In other words: only directories are stored in FileItems.

To solve this problem, a simple solution is to declare a new member field "Parent" in class FileItem, to store the parent FileItem of a file - this field will hold "null" for directories. So the full FileItem class will be:

public class FileItem 
{
    public FileItem? Parent;
    public string? Name { get; set; }
    public string? Path { get; set; }
    public bool IsFolder { get; set; }
    public ObservableCollection<FileItem>? Items { get; set; }
}

We have to make a few changes in function LoadFilesAndFolders to "fill" new field Parent:

    private void LoadFilesAndFolders()
    {
        if (Directory.Exists(_myReSEEptImagesFolder))
        {
            //Grab primary direcotory

            var items = Directory.GetFileSystemEntries(_myReSEEptImagesFolder);

            foreach (var item in items)
            {
                var fileItem = new FileItem
                {
                    Parent = null,
                    Name = Path.GetFileName(item),
                    Path = item,
                    IsFolder = Directory.Exists(item)
                };

                // Load files inside folders

                if (fileItem.IsFolder)
                {
                    var subItems = Directory.GetFileSystemEntries(item);

                    fileItem.Items = new ObservableCollection<FileItem>();

                    foreach (var subItem in subItems)
                    {
                        fileItem.Items.Add(new FileItem
                        {
                            Parent = fileItem,
                            Name = Path.GetFileName(subItem),
                            Path = subItem,
                            IsFolder = Directory.Exists(subItem)
                        });
                    }
                }

                FileItems.Add(fileItem);
            }
        }
    }

And, finally, change also function DeleteItemClicked to use Parent. Lines that change FileCollectionView.ItemsSource are useless (and removed):

    private async void DeleteItemClicked(object sender, EventArgs e)
    {
        var button = sender as Button;
        var fileItem = button?.BindingContext as FileItem;

        if (fileItem != null)
        {
            bool isConfirmed = await DisplayAlert("Delete", $"Are you sure you want to delete {fileItem.Name}?", "Yes", "No");

            if (isConfirmed)
            {
                try
                {
                    // Delete the file or folder
                    if (File.Exists(fileItem.Path))
                    {
                        File.Delete(fileItem.Path);
                    }
                    else if (Directory.Exists(fileItem.Path))
                    {
                        Directory.Delete(fileItem.Path, true);
                    }

                    // Remove the item from the collection

                    if (fileItem.Parent == null)
                    {
                        FileItems.Remove(fileItem);
                    }
                    else
                    {
                        fileItem.Parent?.Items?.Remove(fileItem);
                    }
                }
                catch (Exception ex)
                {
                    await DisplayAlert("Error", $"Failed to delete {fileItem.Name}: {ex.Message}", "OK");
                }
            }
        }
    }

I hope that I was helpful.

发布评论

评论列表(0)

  1. 暂无评论