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

Posted

技术标签:

【中文标题】如何在 Avalonia 应用程序中为 OpenFolderDialog 设置标题?【英文标题】:How to set Title for OpenFolderDialog in an Avalonia application? 【发布时间】:2020-11-29 01:27:03 【问题描述】:

我正在使用 Avalonia 应用程序中的 OpenFileDialogSaveFileDialogOpenFolderDialog。 一项要求是将标题设置为某个字符串。 我为 OpenFileDialogSaveFileDialog 实现了这一点,但 notOpenFolderDialogOpenFolderDialog 拒绝应用标题,因此只保留了根据操作系统语言的默认标题设置。 我发现在ControlCatalogStandalone 中OpenFolderDialog 工作正常,即可以根据需要设置标题。 因此,我尝试将 ControlCatalogStandalone 简化为 Dialogs 功能,并将其转换为尽可能类似于我的测试应用程序。 我无法做到这一点,但我发现了一些线索,可以帮助更熟练的开发人员找到我的测试应用程序行为不端的原因。ControlCatalogStandaloneSolutionProject 的结构和组成与我的 Avalonia 测试应用程序大不相同。 在我的测试应用程序中,目标框架是.NET Core 3.1。 在 ControlCatalogStandalone 解决方案的一个项目中,目标框架是 .NET Standard 2.0。 所以,我认为OpenFolderDialog.NET Standard 中是正确的,但在.NET Core 中不是。 我还认为,如果 ControlCatalogStandalone 是使用当前版本的 Avalonia for Visual Studio 扩展从头开始构建的,它不会产生混合框架。 以下是我的测试应用程序的相关代码部分: 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.asaml.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);
        
    

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

【问题讨论】:

【参考方案1】:

我不熟悉/不熟悉 Avalon 框架,因此我不会对您的不同设置测试发表过多评论。然而,OpenFolderDialog 似乎有一个错误,它在显示时没有设置标题,至少对于它的 Windows 实现。这被报告为 github 源上的一个问题,似乎尚未解决:

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

(与 FileDialog 的 here 相比)。 参考:https://github.com/AvaloniaUI/Avalonia/issues/3037

没有进一步挖掘源代码,不清楚为什么ControlCatalogStandalone 示例正常运行,因为它似乎在#ShowAsync 中使用相同的方法(使用here),它被定义为here。

【讨论】:

你说得对,这是框架中的一个错误。我认为它适用于 ControlCatalog 示例,因为他们在那里使用自定义样式的文件夹选择器对话框,不是吗? 我正在对此问题进行更多调查,以清楚地显示 OpenFolderDialog 在 ControlCatalogStandalone 应用程序和我自己的测试应用程序中的不同行为。我已经上传了我的测试应用程序和 ControlCatalogStandalone 应用程序的全部源代码,我将其简化为对话框功能,但现在我认为它们不再需要了。感谢大家的信息,感谢您新创建的问题。

以上是关于如何在 Avalonia 应用程序中为 OpenFolderDialog 设置标题?的主要内容,如果未能解决你的问题,请参考以下文章

如何在代码中制作与 Avalonia UI 兼容的位图?

在 Avalonia 中设置窗口图标

Avalonia 通知导致应用程序崩溃

如何在 Avalonia 中绑定颜色

如何在 Avalonia.ReactiveUI 中使用 Autofac 作为 DI 容器?

Avalonia:如何使用代码为路径中的点设置动画