Repository: beeware/toga

Issue:
Open_File_Dialog crashes on W10 with custom file_type
following code:
```
fname = self.main_window.open_file_dialog(
  title="Open RTF file",
  multiselect=False,
  file_types=['rtf']
)
```

## Expected Behavior
should work fine ond every platform

## Current Behavior
works fine on linux, crashes on Windows 10:
```
Traceback (most recent call last):
  File "C:\Users\user\AppData\Local\Programs\NewGAN Manager\\app\newganmanager\app.py", line 301, in action_open_file_dialog
    file_types=['rtf']
  File "C:\Users\user\AppData\Local\Programs\NewGAN Manager\\app_packages\toga\window.py", line 282, in open_file_dialog
    return self._impl.open_file_dialog(title, initial_directory, file_types, multiselect)
  File "C:\Users\user\AppData\Local\Programs\NewGAN Manager\\app_packages\toga_winforms\window.py", line 182, in open_file_dialog
    "|All files (*.*)|*.*"
System.ArgumentException: Die angegebene Filterzeichenfolge ist ungültig. Sie muss eine Beschreibung des Filters gefolgt von einem vertikalen Strich (|) und dem Filtermuster enthalten. Die Zeichenfolgen für andere Filteroptionen müssen ebenfalls durch einen vertikalen Strich getrennt werden. Beispiel: "Textdateien (*.txt)|*.txt|Alle Dateien (*.*)|*.*".
   bei System.Windows.Forms.FileDialog.set_Filter(String value)
```
Translated: The provided filter-string is invalid. It must consist of a description of the filter a vertical bar (|) and the filter-pattern. Following the example of the FIXME

## Steps to reproduce
see snippet.

* Python Version (list the specific version number)
python 3.7

* Operating System and Version (select from the following and list the specific version number; if your OS is not listed, list that as well)

  - [x] Windows - version: 10


* Toga Version (list the specific version number or git hash)

* Toga Target (the type of app you are trying to generate)

  - [ ] android
  - [ ] cocoa
  - [ ] django
  - [x] gtk
  - [ ] iOS
  - [ ] tvOS
  - [ ] watchOS
  - [x] winforms
  - [ ] win32
  - [ ] Other (please specify)

## Proposed Solution
change https://github.com/beeware/toga/blob/master/src/winforms/toga_winforms/window.py#L181
to
```
file_string = "{0} files (*.{0})|*.{0}"
fil = '|'.join([file_string.format(ext) for ext in file_types]) + \
                            "|All files (*.*)|*.*"

```
This is ofc not an ideal solution, because we just add a generic description, but since there is no wrapper for an appropriate datatype I feel this would be a reasonable bridging solution.

src: https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.filedialog.filter?view=netcore-3.1

P.S: I can't contribute to windows myself, because I barely get my hands on a W10 machine and I just had a few minutes to test it out. Cheers


Discussion:

Resolving patch:
diff --git a/src/winforms/toga_winforms/window.py b/src/winforms/toga_winforms/window.py
--- a/src/winforms/toga_winforms/window.py
+++ b/src/winforms/toga_winforms/window.py
@@ -176,10 +176,7 @@ def open_file_dialog(self, title, initial_directory, file_types, multiselect):
         if initial_directory is not None:
             dialog.InitialDirectory = initial_directory
         if file_types is not None:
-            # FIXME This is the example of Filter string: Text files (*.txt)|*.txt|All files (*.*)|*.*
-
-            dialog.Filter = ';'.join(["*." + ext for ext in file_types]) + \
-                            "|All files (*.*)|*.*"
+            dialog.Filter = self.build_filter(file_types)
         if multiselect:
             dialog.Multiselect = True
         if dialog.ShowDialog() == WinForms.DialogResult.OK:
@@ -197,3 +194,8 @@ def select_folder_dialog(self, title, initial_directory, multiselect):
             return [dialog.SelectedPath]
         else:
             raise ValueError("No folder provided in the select folder dialog")
+
+    def build_filter(self, file_types):
+        file_string = "{0} files (*.{0})|*.{0}"
+        return '|'.join([file_string.format(ext) for ext in file_types]) + \
+            "|All files (*.*)|*.*"


Test patch:
diff --git a/src/winforms/tests/test_window.py b/src/winforms/tests/test_window.py
new file mode 100644
--- /dev/null
+++ b/src/winforms/tests/test_window.py
@@ -0,0 +1,12 @@
+from toga_dummy.utils import TestCase
+from toga_winforms import window
+
+
+class TestWindow(TestCase):
+    def setUp(self):
+        super().setUp()
+        self.window = window.Window
+
+    def test_build_filter(self):
+        test_filter = self.window.build_filter(None, ["txt"])
+        self.assertEqual(test_filter, "txt files (*.txt)|*.txt|All files (*.*)|*.*")