自定义 OpenFileDialog 修改按钮文字

Customizing OpenFileDialog to modify button text

我想要一个文件夹对话框来获取所选文件夹的路径,并希望将多个文件保存到该路径。

我可以使用 WindowsApiCodePack

得到这个

我想将按钮 "Select folder" 中的文本重命名为 "Save",这是我的客户建议的,除了更改之外没有其他方法可以满足他们的要求。

但是,我可以更改对话框的标题,但不能更改按钮文本。

如何修改按钮文字?

这应该可行

 var dialog = new CommonOpenFileDialog();
 dialog.IsFolderPicker = true;    
 dialog.SetOpenButtonText("SAVE TO THIS FOLDER");

如果您使用的是 this 版本的包,那么我认为没有简单的开箱即用解决方案。可以做到,但需要一些反射才能起作用(如果有人找到更简单的方法,请分享)。

首先,您必须在您的项目中引用 System.Windows.Forms 程序集(如果您还没有)。

然后,你至少mock-use了一次,所以方法GetReferencedAssemblies() returns就可以了(再说一次,如果你无论如何都用它,你可以跳过这一步),下面一行代码就足够了:

Form f=null;

现在,这是一个 class 有几个方法可以使必要的反思更容易:

public class MyReflector
{
    string myNamespace;
    Assembly myAssembly;
    public MyReflector(string assemblyName, string namespaceName)
    {
        myNamespace = namespaceName;
        myAssembly = null;
        var alist=Assembly.GetExecutingAssembly().GetReferencedAssemblies();
        foreach (AssemblyName aN in alist)
        {
            if (aN.FullName.StartsWith(assemblyName))
            {
                myAssembly = Assembly.Load(aN);
                break;
            }
        }
    }
    public Type GetType(string typeName)
    {
        Type type = null;
        string[] names = typeName.Split('.');

        if (names.Length > 0)
            type = myAssembly.GetType(myNamespace + "." + names[0]);

        for (int i = 1; i < names.Length; ++i)
        {
            type = type.GetNestedType(names[i], BindingFlags.NonPublic);
        }
        return type;
    }

    public object Call(Type type, object obj, string func, object[] parameters)
    {
        MethodInfo methInfo = type.GetMethod(func, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
        return methInfo.Invoke(obj, parameters);
    }

    public object GetField(Type type, object obj, string field)
    {
        FieldInfo fieldInfo = type.GetField(field, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
        return fieldInfo.GetValue(obj);
    }
}

最后,设置按钮文本的代码。

    CommonOpenFileDialog ofp = new CommonOpenFileDialog();
    ofp.IsFolderPicker = true;

    // In the CommonFileDialog in WindowsAPICodePack, there is a nativeDialog field of type IFileDialog
    // get it first and check if it's not null:
    var r1 = new MyReflector("Microsoft.WindowsAPICodePack", "Microsoft.WindowsAPICodePack");
    Type typeCommonFileDialog = typeof(CommonFileDialog);
    object nativeDialog = r1.GetField(typeCommonFileDialog, ofp, "nativeDialog");
    if (nativeDialog == null)
    {
        // if nativeDialog was null, initialize it:
        r1.Call(ofp.GetType(), ofp, "InitializeNativeFileDialog", new object[]{});
        nativeDialog = r1.Call(ofp.GetType(), ofp, "GetNativeFileDialog", new object[] { });
    }

    // call SetOkButtonLabel method on nativeDialog object
    var r2 = new MyReflector("System.Windows.Forms", "System.Windows.Forms");
    Type typeIFileDialog = r2.GetType("FileDialogNative.IFileDialog");
    r2.Call(typeIFileDialog, nativeDialog, "SetOkButtonLabel",new object[] { "Save" });

    ofp.ShowDialog();

解释:

WindowsAPICodePack 中,CommonOpenFileDialogCommonFileDialog class 的子 class。在 CommonFileDialog 中,有一个类型为 IFileDialognativeDialog 字段(类型 IFileDialog 也不是 public)。您可以使用它来设置按钮的文本。可悲的是,它是私人的。它在仅调用构造函数后也不会初始化(尽管有些方法会初始化它,因此您必须在开始时检查它是否为 null)。 IFileDialog 有一个内部方法 SetOkButtonLabel。这就是你需要的。