using System.Windows; using System.Windows.Controls; using Microsoft.SharePoint.Client; using SharepointToolbox.Core.Helpers; namespace SharepointToolbox.Views.Dialogs; public partial class FolderBrowserDialog : Window { private readonly ClientContext _ctx; public string SelectedLibrary { get; private set; } = string.Empty; public string SelectedFolderPath { get; private set; } = string.Empty; public FolderBrowserDialog(ClientContext ctx) { InitializeComponent(); _ctx = ctx; Loaded += OnLoaded; } private async void OnLoaded(object sender, RoutedEventArgs e) { try { // Load libraries var web = _ctx.Web; var lists = _ctx.LoadQuery(web.Lists .Include(l => l.Title, l => l.Hidden, l => l.BaseType, l => l.RootFolder) .Where(l => !l.Hidden && l.BaseType == BaseType.DocumentLibrary)); var progress = new Progress(); await ExecuteQueryRetryHelper.ExecuteQueryRetryAsync(_ctx, progress, CancellationToken.None); foreach (var list in lists) { var libNode = new TreeViewItem { Header = list.Title, Tag = new FolderNodeInfo(list.Title, string.Empty), }; // Add dummy child for expand arrow libNode.Items.Add(new TreeViewItem { Header = "Loading..." }); libNode.Expanded += LibNode_Expanded; FolderTree.Items.Add(libNode); } StatusText.Text = $"{FolderTree.Items.Count} libraries loaded."; } catch (Exception ex) { StatusText.Text = $"Error: {ex.Message}"; } } private async void LibNode_Expanded(object sender, RoutedEventArgs e) { if (sender is not TreeViewItem node || node.Tag is not FolderNodeInfo info) return; // Only load children once if (node.Items.Count == 1 && node.Items[0] is TreeViewItem dummy && dummy.Header?.ToString() == "Loading...") { node.Items.Clear(); try { var folderUrl = string.IsNullOrEmpty(info.FolderPath) ? GetLibraryRootUrl(info.LibraryTitle) : info.FolderPath; var folder = _ctx.Web.GetFolderByServerRelativeUrl(folderUrl); _ctx.Load(folder, f => f.Folders.Include(sf => sf.Name, sf => sf.ServerRelativeUrl)); var progress = new Progress(); await ExecuteQueryRetryHelper.ExecuteQueryRetryAsync(_ctx, progress, CancellationToken.None); foreach (var subFolder in folder.Folders) { if (subFolder.Name.StartsWith("_") || subFolder.Name == "Forms") continue; var childNode = new TreeViewItem { Header = subFolder.Name, Tag = new FolderNodeInfo(info.LibraryTitle, subFolder.ServerRelativeUrl), }; childNode.Items.Add(new TreeViewItem { Header = "Loading..." }); childNode.Expanded += LibNode_Expanded; node.Items.Add(childNode); } } catch (Exception ex) { node.Items.Add(new TreeViewItem { Header = $"Error: {ex.Message}" }); } } } private string GetLibraryRootUrl(string libraryTitle) { var uri = new Uri(_ctx.Url); return $"{uri.AbsolutePath.TrimEnd('/')}/{libraryTitle}"; } private void FolderTree_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs e) { if (e.NewValue is TreeViewItem node && node.Tag is FolderNodeInfo info) { SelectedLibrary = info.LibraryTitle; SelectedFolderPath = info.FolderPath; SelectButton.IsEnabled = true; } } private void Select_Click(object sender, RoutedEventArgs e) { DialogResult = true; Close(); } private void Cancel_Click(object sender, RoutedEventArgs e) { DialogResult = false; Close(); } private record FolderNodeInfo(string LibraryTitle, string FolderPath); }