如何在Avalonia应用程序中设置OpenFolderDialog的标题?

8

我正在使用 Avalonia 应用程序中的 OpenFileDialogSaveFileDialogOpenFolderDialog
其中一个要求是设置标题为特定字符串。
我已经实现了 OpenFileDialogSaveFileDialog 的标题设置,但是对于 OpenFolderDialog 没有实现。
OpenFolderDialog 抵制应用标题,因此只设置了操作系统语言的默认标题。

我发现在 ControlCatalogStandalone 中,OpenFolderDialog 可以正常工作,即可以设置所需的标题。
因此,我尝试将 ControlCatalogStandalone 缩减到 Dialogs 功能,并尽可能使其与我的测试应用程序相似。
我无法做到这一点,但是我找到了一些线索,这可能有助于更有经验的开发人员找到我的测试应用程序出现问题的原因。

解决方案项目ControlCatalogStandalone 结构和组成方式与我的 Avalonia 测试应用程序大不相同。
在我的测试应用程序中,目标框架是 .NET Core 3.1
ControlCatalogStandalone 解决方案的一个项目中,目标框架是 .NET Standard 2.0
因此,我认为 OpenFolderDialog.NET Standard 中可以正常工作,但在 .NET Core 中不能正常工作。
我还认为,如果使用当前版本的 Avalonia for Visual Studio 扩展从头构建 ControlCatalogStandalone,它将不会产生混合框架。

这是我的测试应用程序的相关代码部分:

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);
        }
    }
}

我显示最后一个文件是因为我无法在我的ViewModel中实现方法Window GetWindow() => (Window)this.VisualRoot;,这个方法在ControlCatalogStandalone 中被实现并在DialogsPage的代码后台中使用(实际上是一个UserControl)。所以,我实现了Instance属性,这可能是一种hack方式。如果您也可以给我提示如何获取MainWindow的实例,我会很高兴。我的问题是无法在OpenFolderDialog中设置标题,这是.NET Core实现的一个未解决问题,还是您能告诉我如何让它在我的简单测试应用程序中工作?
1个回答

1
我不熟悉Avalon框架,所以对于你的不同设置测试不会过多评论。然而,似乎OpenFolderDialog存在一个bug,在Windows实现中展示时没有设置标题。这在github源中被报告为一个问题,目前似乎还没有解决:

文件夹对话框缺少frm.SetTitle: Windows/Avalonia.Win32/SystemDialogImpl#L116

相对于FileDialog的这里,参考:https://github.com/AvaloniaUI/Avalonia/issues/3037

不需要进一步深入源代码,不清楚为什么ControlCatalogStandalone示例可以正常运行,因为它似乎使用了与#ShowAsync(在这里使用)相同的方法,该方法在这里中定义。


你说得对,这是框架中的一个错误。我认为它在“ControlCatalog”示例中工作是因为他们在那里使用了自定义样式的文件夹选择对话框,不是吗? - frankenapps
我正在更深入地研究这个问题,以清楚地展示 OpenFolderDialog 在 ControlCatalogStandalone 应用程序和我的测试应用程序中的不同行为。 我已经上传了我的测试应用程序和 ControlCatalogStandalone 应用程序的全部源代码,但现在我认为它们不再需要了。 感谢大家提供的信息,也感谢你们创建了这个新的问题。 - Zoldan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接