How to set Title for OpenFolderDialog in an Avalonia application?
Asked Answered
L

1

8

I'm working with OpenFileDialog, SaveFileDialog and OpenFolderDialog in an Avalonia application.
One requirement is to set the title to a certain string.
I achieved this for OpenFileDialog and SaveFileDialog but not for OpenFolderDialog.
OpenFolderDialog resists applying the title, so that only a default title according the language of the operating system remains set.

I found that in ControlCatalogStandalone the OpenFolderDialog works correct, i.e. the title can be set as desired.
So, I tried to reduce ControlCatalogStandalone to the Dialogs functionality and transform it to be as similar as possible to my test application.
I couldn't achieve that, but I found some clue that might help a more skilled developer to find the reason for the misbehavior of my test application.

The Solution and the Projects of ControlCatalogStandalone are structured and composed much different to my Avalonia test application.
In my test application the target framework is .NET Core 3.1.
In one Project of the ControlCatalogStandalone Solution the target framework is .NET Standard 2.0.
So, I think OpenFolderDialog works correct in .NET Standard but not in .NET Core.
I also think that if ControlCatalogStandalone was built from scratch with the current version of the Avalonia for Visual Studio Extension, it wouldn't produce a mix of frameworks.

Here are the relevant code parts of my test application:

MainWindow.axaml:

<Window xmlns="https://github.com/avaloniaui"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:vm="clr-namespace:DialogTests.ViewModels;assembly=DialogTests"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d" Width="200" Height="150"
        x:Class="DialogTests.Views.MainWindow"
        Icon="/Assets/avalonia-logo.ico"
        Title="DialogTests">

    <Design.DataContext>
        <vm:MainWindowViewModel/>
    </Design.DataContext>

    <Grid RowDefinitions="*,*,*">
        <Button Grid.Column="0" Grid.Row="0" Command="{Binding OpenFileDialogCommand}" Content="OpenFileDialog"/>
        <Button Grid.Column="0" Grid.Row="1" Command="{Binding SaveFileDialogCommand}" Content="SaveFileDialog"/>
        <Button Grid.Column="0" Grid.Row="2" Command="{Binding OpenFolderDialogCommand}" Content="OpenFolderDialog"/>
    </Grid>

</Window>

MainWindowViewModel.cs:

using Avalonia.Controls;
using DialogTests.Views;
using ReactiveUI;
using System.Collections.Generic;
using System.Reactive;

namespace DialogTests.ViewModels
{
    public class MainWindowViewModel : ViewModelBase
    {
        public MainWindowViewModel()
        {
            OpenFileDialogCommand = ReactiveCommand.Create(() => {
                new OpenFileDialog()
                {
                    Title = "Open File Dialog",
                    Filters = GetFilters()
                }.ShowAsync(MainWindow.Instance);
            });

            SaveFileDialogCommand = ReactiveCommand.Create(() =>
            {
                new SaveFileDialog()
                {
                    Title = "Save File Dialog",
                    Filters = GetFilters()
                }.ShowAsync(MainWindow.Instance);
            });

            OpenFolderDialogCommand = ReactiveCommand.Create(() => {
                new OpenFolderDialog()
                {
                    Title = "Open Folder Dialog"
                }.ShowAsync(MainWindow.Instance);
            });
        }

        public ReactiveCommand<Unit, Unit> OpenFileDialogCommand { get; }
        public ReactiveCommand<Unit, Unit> SaveFileDialogCommand { get; }
        public ReactiveCommand<Unit, Unit> OpenFolderDialogCommand { get; }

        List<FileDialogFilter> GetFilters()
        {
            return new List<FileDialogFilter>
                {
                    new FileDialogFilter
                    {
                        Name = "Text files", Extensions = new List<string> {"txt"}
                    },
                    new FileDialogFilter
                    {
                        Name = "All files",
                        Extensions = new List<string> {"*"}
                    }
                };
        }
    }
}

MainWindow.axaml.cs:

using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;

namespace DialogTests.Views
{
    public class MainWindow : Window
    {
        public static MainWindow Instance { get; private set; }
        public MainWindow()
        {
            Instance = this;
            InitializeComponent();
#if DEBUG
            this.AttachDevTools();
#endif
        }

        private void InitializeComponent()
        {
            AvaloniaXamlLoader.Load(this);
        }
    }
}

I'm showing the last file because I wasn't able to implement the method Window GetWindow() => (Window)this.VisualRoot; in my ViewModel which in ControlCatalogStandalone is implemented and used in the code behind of DialogsPage (which actually is a UserControl).
So, I implemented the Instance property which perhaps is a hack.
If you also could give me hint on best practice to get the instance of the MainWindow I'd be happy.

Is my problem not being able to set the title in OpenFolderDialog an open issue of the .NET Core implementation, or can you tell me how to get it working in my simple test application?

Libya answered 9/8, 2020 at 6:46 Comment(0)
T
1

I'm not familiar/experienced with the Avalon framework so I won't comment too much on your different setup tests. However it seems that the OpenFolderDialog has a bug that it doesn't set the title when being showed, atleast for its Windows implementation. This is reported as a issue on the github source, and seems not yet solved:

frm.SetTitle is missing for the folder dialog: Windows/Avalonia.Win32/SystemDialogImpl#L116

(In comparison to here for FileDialog). Reference: https://github.com/AvaloniaUI/Avalonia/issues/3037

Without further digging into the source, its unclear why the ControlCatalogStandalone example functions correctly since it appears to use the same method in #ShowAsync (used here), which is defined here.

Teleplay answered 9/8, 2020 at 8:28 Comment(2)
You are right this is a bug in the framework. I think it works for the ControlCatalog sample because they are using a custom styled folder picker dialog there, aren't they?Patino
I was investigating more on this issue to show clearly the different behavior of OpenFolderDialog in the ControlCatalogStandalone application and in my own test application. I already uploaded the whole sources of my test application and of the ControlCatalogStandalone application which I reduced to the Dialogs functionality, but now I think they are not needed any more. Thank you all for your information and thank you for the new created issue.Libya

© 2022 - 2024 — McMap. All rights reserved.