1

I have the following issues with a bit of my code currently.

I have a folder called FileHandling within my UWP C# project. Within that folder is a class called OpenFileClass.cs

Within the OpenFileClass i have an asynchronous void that allows an openFileDialog to be triggered. The code for that is the following:

public async void OpenFile_ClickAsync(object sender, RoutedEventArgs e)
{
    FileOpenPicker openPicker = new FileOpenPicker
    {
        ViewMode = PickerViewMode.List,
        SuggestedStartLocation = PickerLocationId.DocumentsLibrary

    };
    openPicker.FileTypeFilter.Add(".txt");
    openPicker.FileTypeFilter.Add(".csv");

    StorageFile file = await openPicker.PickSingleFileAsync();
    if (file != null)
    {
        // Application now has read/write privelages for selected file
    }
    else
    {
        // Cancel operation and resume program
    }

}

On the MainPage.xaml.cs I am trying to call the function OpenFile_ClickAsync by doing the following:

using BS.FileHandling;
private void OpenFile_Click(object sender, RoutedEventArgs e)
{
    OpenFileClass.OpenFile_ClickAsync();
}

There is a control on the AppBarButton which has ClickMode="Press" and "Click=OpenFile_Click" which should trigger the function within MainPage.xaml.cs

Now, im pretty new to this and learning slowly but im pretty sure that the openFileDialog has to be an Asynchronous function. Im just not sure how to then call that through another class?

Am I overlooking something small or am I at completely the wrong end of the stick here?

mm8
  • 163,881
  • 10
  • 57
  • 88
Batteredburrito
  • 579
  • 1
  • 5
  • 34
  • 1
    Duplicate of https://stackoverflow.com/questions/9343594/how-to-call-asynchronous-method-from-synchronous-method-in-c – Zysce Sep 05 '18 at 12:50
  • *Don't* try to call `async void` methods. That signature is only meant for event handlers. You don't need to use that `OpenFile_Click` method at all – Panagiotis Kanavos Sep 05 '18 at 12:51
  • Are you trying to call public async void OpenFile_ClickAsync(object sender, RoutedEventArgs e) ? If so, I can see that you have not passed any arguments to it! – Amir Hajiha Sep 05 '18 at 12:52
  • @Zycse not really a duplicate. The OP is trying to call one "event handler" from another, identical one, instead of just calling the proper handler – Panagiotis Kanavos Sep 05 '18 at 12:52
  • @Batteredburrito what are you trying to do here? Call an *event handler* from another method? That's a very, very, very bad idea, even without `async/await - you are mixing business logic with UI logic. Use a *separate* method if you want it to be called by other code. Use `async Task` if it's meant to be asynchronous. Make your `OpenFile_Click` event handler asynchronous as well and call the new method with `await OpenFileClass.MyNewMethod();` – Panagiotis Kanavos Sep 05 '18 at 12:54
  • @PanagiotisKanavos by not having to use OpenFile_Click method, how would i work around this. I assumed i would need to have a handler in the MainPage.xaml where the control is nested? Are you saying i can call the OpenFileClass.OpenFile_ClickAsync directly from the XAML control?? – Batteredburrito Sep 05 '18 at 12:56
  • using await! that makes sense! thank you for the help @PanagiotisKanavos – Batteredburrito Sep 05 '18 at 12:56
  • @Batteredburrito I didn't say this, but you can. `Click=OpenFile_Click` is an *expression* that can point to nested objects. It can even be a data binding expression. WPF isn't Windows Forms. Events and commands don't have to be handled by the code-behind and typically *shouldn't* be handled by it. Imagine trying to pick a file in response to a button *or* a menu item. With WPF you can bind both of them to the same command – Panagiotis Kanavos Sep 05 '18 at 12:59
  • Okay. Im sorry for the bounce around. Im still trying to get to grips with all this and knowledge is limited at this point. I believe you guys have clarified it though and ill see what i can impliment :) – Batteredburrito Sep 05 '18 at 13:01
  • @Batteredburrito check [this question](https://stackoverflow.com/questions/3531772/binding-button-click-to-a-method?rq=1) for example. The button is bound to a command on the *ViewModel* with ``. – Panagiotis Kanavos Sep 05 '18 at 13:01
  • @PanagiotisKanavos I feel like im being incredibly stupid but would the example provided still not push me into the same kind of issue. Would you mind if i migrated to a discussion with you for some further assistance, understandable if not. I may be able to explain better – Batteredburrito Sep 05 '18 at 13:12

1 Answers1

1

OpenFileClass should contain a method that opens, and probably also returns, a file. It shouldn't contain any event handlers. It might look something like this:

public class OpenFileClass
{
    public async Task<IStorageFile> OpenFileAsync()
    {
        FileOpenPicker openPicker = new FileOpenPicker
        {
            ViewMode = PickerViewMode.List,
            SuggestedStartLocation = PickerLocationId.DocumentsLibrary

        };
        openPicker.FileTypeFilter.Add(".txt");
        openPicker.FileTypeFilter.Add(".csv");

        return await openPicker.PickSingleFileAsync();
    }
}

Note that the method is named *Async according to the convention, and returns a Task. Asynchronous methods should not return void - except for event handlers.

You could then use this method throughout your application by simply creating an instance of the class and await the OpenFileAsync() method:

private async void OpenFile_Click(object sender, RoutedEventArgs e)
{
    OpenFileClass instance = new OpenFileClass();
    IStorageFile file = await instance.OpenFileAsync();
}
mm8
  • 163,881
  • 10
  • 57
  • 88