I wanted a folder dialog box to get the path of a folder that is selected and wanted to save multiple files in to that path.
I am able to get this using WindowsApiCodePack
I want to rename the text in the button "Select folder" to "Save" which was suggested by my clients and there is no other way to satisfy them except to change that.
However, I am able to change the title of the dialog box, but not the button text.
How can I modify the button text?
If you are using this version of the pack, then I don't think there is an easy out-of-the-box soloution. It can be done, but it requires a bit of Reflection to work (if someone found a simpler way, please do share).
First, you have to reference System.Windows.Forms
asembly in your project (if you don't have it already).
Then, you mock-use it at least once, so the method GetReferencedAssemblies()
returns it (again, if you use it anyway, you can skip this step), the following line of code will suffice:
Form f=null;
Now, this is a class with a few methods to make the necessary reflection easier:
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);
}
}
Finally, the code to set the button's text.
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();
EXPLANATION:
In WindowsAPICodePack
, CommonOpenFileDialog
is a subclass of CommonFileDialog
class. In the CommonFileDialog
, there is a nativeDialog
field of type IFileDialog
(the type IFileDialog
also isn't public). You can use it to set the text of a button. Sadly, it's private. It is also not initialized after calling just the constructor (some methods initialize it though, so you have to check if it's null at the start). IFileDialog
has an internal method SetOkButtonLabel
. That's what you need.