System.Windows.forms.SavefileDialog لا يفرض التمديد الافتراضي
-
22-09-2019 - |
سؤال
أحاول أن أجعل SaveFileDialog
و FileOpenDialog
فرض امتداد إلى اسم الملف الذي أدخله المستخدم. لقد حاولت استخدام العينة المقترحة في سؤال 389070 لكنه لا يعمل كما هو مقصود:
var dialog = new SaveFileDialog())
dialog.AddExtension = true;
dialog.DefaultExt = "foo";
dialog.Filter = "Foo Document (*.foo)|*.foo";
if (dialog.ShowDialog() == DialogResult.OK)
{
...
}
إذا كتب المستخدم النص test
في مجلد حيث ملف test.xml
يحدث ، سيقترح الحوار الاسم test.xml
(بينما أريد فقط أن أرى فقط *.foo
في القائمة). أسوأ من ذلك: إذا اختار المستخدم test.xml
, ، ثم سأحصل بالفعل test.xml
كاسم ملف الإخراج.
كيف يمكنني التأكد من ذلك SaveFileDialog
حقًا يسمح للمستخدم فقط بتحديد ملف *.foo
ملف؟ أو على الأقل ، أنه يستبدل/يضيف الامتداد عندما ينقر المستخدم Save
?
الحلول المقترحة (تنفيذ FileOk
معالج الأحداث) لا تفعل سوى جزء من الوظيفة ، حيث أرغب حقًا في تعطيل Save
الزر إذا كان اسم الملف يحتوي على امتداد خاطئ.
من أجل البقاء في الحوار و قم بتحديث اسم الملف المعروض في مربع النص في FileOk
معالج ، لتعكس اسم الملف الجديد مع الامتداد الصحيح ، راجع السؤال التالي ذي الصلة.
المحلول
AFAIK لا توجد طريقة موثوقة لفرض امتداد ملف معين. إنها ممارسة جيدة على أي حال للتحقق من الامتداد الصحيح ، بمجرد إغلاق مربع الحوار وإبلاغ المستخدم بأنه قد حدد ملفًا غير صالح إذا لم يتطابق الامتداد.
نصائح أخرى
يمكنك التعامل مع FileOk
الحدث ، وإلغاءه إذا لم يكن الامتداد الصحيح
private saveFileDialog_FileOk(object sender, CancelEventArgs e)
{
if (!saveFileDialog.FileName.EndsWith(".foo"))
{
MessageBox.Show("Please select a filename with the '.foo' extension");
e.Cancel = true;
}
}
أقرب ما وصلت إلى هذا هو باستخدام حدث FileoK. علي سبيل المثال:
dialog.FileOk += openFileDialog1_FileOk;
private void openFileDialog1_FileOk(object sender, System.ComponentModel.CancelEventArgs e)
{
if(!dialog.FileName.EndsWith(".foo"))
{
e.Cancel = true;
}
}
الدفع حدث FileoK على MSDN.
واجهت هذه المشكلة نفسها ، وتمكنت من التحكم في ما تم عرضه من خلال القيام بما يلي:
مع OpenFileDialog ، كان العنصر الأول في سلسلة التصفية هو الافتراضي
openFileDialog1.Filter = "Program x Files (*.pxf)|*.pxf|txt files (*.txt)|*.txt";
openFileDialog1.ShowDialog();
مع SaveFileDialog ، تم استخدام العنصر الثاني في المرشح كإعداد افتراضي:
SaveFileDialog saveFileDialog1 = new SaveFileDialog();
saveFileDialog1.Filter = "txt files (*.txt)|*.txt|Program x Files (*.pxf)|*.pxf";
saveFileDialog1.FilterIndex = 2;
saveFileDialog1.RestoreDirectory = true;
if (saveFileDialog1.ShowDialog() == DialogResult.OK)
{
if (saveFileDialog1.FileName != null)
{
// User has typed in a filename and did not click cancel
saveFile = saveFileDialog1.FileName;
MessageBox.Show(saveFile);
saveCurrentState();
}
}
بعد استخدام هذين المرشحين مع المرشحين المعنيين ، حدثت النتائج المتوقعة أخيرًا. بشكل افتراضي ، عندما يحدد المستخدم زر حفظ ويظهر SaveFileDialog ، فإن fileType المحدد هو نوع ملفات البرنامج المحددة في المرشح لـ SaveFileDialog. وبالمثل ، فإن fileType المحدد لـ OpenFileDialog هو نوع ملفات البرنامج X المحددة في المرشح لـ OpenFileDialog.
سيكون من الجيد أيضًا القيام ببعض التحقق من صحة المدخلات كما هو مذكور أعلاه في هذا الموضوع. أردت فقط أن أشير إلى أن المرشحات تبدو مختلفة بين الحوار على الرغم من أن كلاهما يرث فئة FileDialog.
//this must be ran as administrator due to the change of a registry key, but it does work...
private void doWork()
{
const string lm = "HKEY_LOCAL_MACHINE";
const string subkey = "\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\AutoComplete";
const string keyName = lm + subkey;
int result = (int)Microsoft.Win32.Registry.GetValue(keyName, "AutoComplete In File Dialog", -1);
MessageBox.Show(result.ToString());
if(result.ToString() == "-1")
{
//-1 means the key does not exist which means we must create one...
Microsoft.Win32.Registry.SetValue(keyName, "AutoComplete In File Dialog", 0);
OpenFileDialog ofd1 = new OpenFileDialog();
ofd1.ShowDialog();
}
if (result == 0)
{
//The Registry value is already Created and set to '0' and we dont need to do anything
}
}