Async Dependency Injection in View - c#

I'm trying to use the Repository pattern to manage my Service Access in a WPF application.
So basically I plan on using Ninject to inject my Singleton ServiceManager into each view that needs it.
I've built the ServiceManager so that each method call is asynchronous.
Now I've hit a snag. I'm creating a View that contains a DataGrid, populated by a slow, asychronous method. Currently I have the call in teh constructor but I obviously can't make the constructor asynchronous.
public partial class OffersView : UserControl
{
public OffersView(ISvcManager svcManager)
{
InitializeComponent();
Offers.ItemsSource = await svcManager.GetLatestOffers();
}
}
I can think of a couple of ways around this, eg I could separate the interface into fast methods and slow methods, and use async only for the slow ones with the synchronous fast methods being the ones called in Constructors. Not sure if this is the best approach to use though - and where would be the best place to call a long-running method to populate the datagrid?
Alternatively, I put a Wait() in there and only set the ItemSource after this completes. I REALLY don't like that approach.
So how should I be setting this one up?

Use an asynchronous event handler like Loaded, which will allow for async calls.
For example
public partial class OffersView : UserControl {
private readonly ISvcManager svcManager;
public OffersView(ISvcManager svcManager) {
this.svcManager = svcManager;
InitializeComponent();
Loaded += onLoaded;
}
private async void onLoaded(Object sender, RoutedEventArgs e) {
Loaded -= onLoaded; // Unsubscribe to prevent repeated firing.
Offers.ItemsSource = await svcManager.GetLatestOffers();
}
}

Related

How to use async-await in Unity3d?

I want to use Async-await tasks in my Unity3d game for IO, Network and other operations. I know I can use IEnumerators and Coroutines, but those have a very limited functionality and fails to work while working with Web Service APIs using TcpClient, HttpClient and other async tasks in C#.
I cannot work with UI Components while in async Task. Suppose I get a string from a Web API, I cannot set Text field's text from async task. How can it be done.
There are many solutions to this problem.
Two very similar implementations are UnityMainThreadDispatcher and Microsoft's own UnityDispatcher
They implement running IEnumerators and Actions to be on the main thread respectively. Both rely on a MonoBehaviour pseudo singleton.
This answer goes into a some more detail and shows an alternative implementation.
Searched all over the internet, but didn't find a proper way to achieve async-await in Unity. Some say to use external plugin, some say not possible. No proper answer. Hence, here is the proper way of doing it.
Like most application frameworks, Unity game runs on main UI thread. Hence changing UI elements from an async task doesn't work as we need to call Unity's API only from a Main thread like calling from Methods and IEnumerators. Methods and IEnumerators run on main UI thread.
Also Unity doesn't provide a method to call Main thread like .Net does in Xamarin.Forms (Device.BeginInvokeOnMainThread).
For that we need to use MVVM architecture. MVVM stands for Model-View-ViewModel. We don't need to import anything, just change the way our project works.
By default, Unity uses singleton approach and doesn't provide any application building
framework. Hence MVVM would be better for making versatile games. Using MVVM, we can standardize our code by splitting UI Management, our Application's logic and Data, by splitting Models, Views and logic. MVVM is widely used in cross platform application development.
In MVVM we bind controls (UI Components) to the properties in ViewModel, and we only change properties in ViewModel. Then ViewModel notifies these property changes to the View and thus those changes are reflected in UI components in our scene.
Create a ViewModel Class
public class MainSceneViewModel : INotifyPropertyChanged
{
public string Title { get { return title; } set { title = value; OnPropertyChanged(nameof(Title)); } }
string title;
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
In your Scene Script (Attach to a Gameobject in Unity Inspector).
public class MainSceneScript : MonoBehaviour
{
public Text SceneTitle; // Assign Text Component in Unity Inspector
MainSceneViewModel mainSceneViewModel = new MainSceneViewModel();
void Start()
{
mainSceneViewModel.PropertyChanged += ViewModelPropertyChanged;
DelayedTitleChange();
}
async void DelayedTitleChange()
{
await Task.Delay(2000);
mainSceneViewModel.Title = "This is the Main Scene";
}
// Will be called whenever a property of `MainSceneViewModel` is updated.
void ViewModelPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(MainSceneViewModel.Title))
{
SceneTitle.text = mainSceneViewModel.Title;
}
}
// Clean up
void Dispose()
{
mainSceneViewModel.PropertyChanged -= ViewModelPropertyChanged;
}
}
We can also use Model and notify property changed of that model.

Is there a way to handle the event when a new thread is created in the current process?

I want to able to detect when a new thread is created e.g. Task.Run and, if possible, handle when its closed.
I know it's possible to get the current threads being handled by your process via Process.GetCurrentProcess().Threads and that's somewhat useful. What I want though it's to handle when a new thread begin it's execution, from a perspective that I don't know where it's been created.
Some background
As it was asked, I'm putting here some detail to the actual problem I'm running into, because maybe I'm searching for the least optimal solution.
I'm developing a large system with multiple screen, each one with a bunch of controls, which some of them are custom. Recently, the team has gradually been adopting async/await patterns and the issue of locking the UI untill a task is completed has risen. We created a loading panel in our base form, exposing a hide and show method to be called by the implementations of this base form. The problem here is returning to all those forms that are already implemented and placing calls to those methods throughout the code, especially async events. Here I wonder if there's an easier solution that will work for the past implementations and eliminate the need of calling methods between events.
What we are doing as in today, is something along the lines:
public class BaseForm {
public ShowPanel(){
...
}
public HidePanel(){
...
}
}
public class FormImplementation : BaseForm {
private async void OnEventAsync(object sender, EventArgs e){
ShowPanel();
// await stuff
HidePanel();
}
}
I find it to be quite cumbersome to manually place those calls around event handlers. I'd do some metaprogramming karate, but I'm not experienced with it in C#.
maybe I'm searching for the least optimal solution.
Examining threads is definitely an incorrect approach. For one, async doesn't use threads, so that approach would not have worked.
I find it to be quite cumbersome to manually place those calls around event handlers. I'd do some metaprogramming karate, but I'm not experienced with it in C#.
Metaprogramming is one option, and a pretty decent one. PostSharp and Fody are both highly regarded. The "do something at the beginning and end of these methods" is a common problem in that field, and metaprogramming is a definite option. I think what you actually want is something like this:
public class BaseForm {
public ShowPanel() {
...
}
public HidePanel() {
...
}
}
public class FormImplementation : BaseForm {
private async void OnEventAsync(object sender, EventArgs e) {
ShowPanel();
try { ... }
finally { HidePanel(); }
}
}
You can minimize the code changes by using a disposable, e.g., (using my Nito.Disposables library) with a C# 8 using declaration:
public class BaseForm {
public IDisposable ShowPanel() {
...
return new AnonymousDisposable(HidePanel);
}
private void HidePanel() {
...
}
}
public class FormImplementation : BaseForm {
private async void OnEventAsync(object sender, EventArgs e) {
using var _ = ShowPanel();
...
}
}
There are other alternatives, such as changing the return type of OnEventAsync to be Task, but that would require more code changes I think than just doing the above.

Where to unsubscribe from events?

E.g. for a general type, which subscribe to some events in constructor:
class SomeType
{
public SomeType(...)
{
someEvent1 += ...
someEvent2 += ...
}
}
Where do I unsubscribe from events?
Finalizer?
IDisposable ?
Some method DontForgetToCallMeSoICanUnsubscribeFromEvents()?
Use weak events pattern?
I know it depends. In case of controls (wpf, winforms) there are some events what can be used to subscribe/unsubscribe like Loaded/Unloaded, HandleCreated/HandleDestroyed, etc. But what if parent is a simple object?
And some more specific example: nested ViewModels, where each level is a List<NextLevelVM>, at any level ViewModel can be deleted, does that means what each ViewModel must implement IDisposable (if e.g. it is the right way) where it call Dispose for each item in their list? I tried to use weak events, but that doesn't go well.
I've found a really good way to handle this issue is to create two methods in the page's code behind, that calls methods on your ViewModel to start/stop listening to events depending on whether it's visible or not.
Below I'm using the Appearing functions, but depending on the framework you're using it might be slightly different, but the strategy should work.
In Page class:
protected override void OnAppearing()
{
base.OnAppearing();
_myViewModel.StartListeningToEvents();
}
protected override void OnDisappearing()
{
base.OnDisappearing();
_myViewModel.StopListeningToEvents();
}
Then in my ViewModel, I actually subscribe to the events I require:
public void StartListeningToEvents()
{
SomeProperty.PropertyChanged += PropertyUpdated;
}
public void StopListeningToEvents()
{
SomeProperty.PropertyChanged -= PropertyUpdated;
}
void PropertyUpdated(object sender, PropertyChangedEventArgs e)
{
// do stuff
}
My example is for a property change event. But similar code should work for any event.
In this way you're guaranteed that your page is only listening to events when it's open, and you don't need to worry about disposing anything besides calling the one event when the page is no longer open.

How can I wait Until a Form Handle Has Been Created Before Using Its' Components?

I am dynamically instantiating a Form. I cannot interact with the components (such as a TextBox) on the Form until the handle has been created (else, an exception will be thrown).
Currently I block the thread using a while loop:
public void OutputDesktopFrame(MessagingService service, DesktopFrame desktopFrame)
{
IRemoteDesktopView view = GetView(service);
view.UpdateFrame(desktopFrame);
}
private IRemoteDesktopView GetView(MessagingService service)
{
T view;
bool viewExists = _views.TryGetValue(service, out view);
if (viewExists == false)
{
view = CreateAndShowView(service);
}
return view;
}
private T CreateAndShowView(MessagingService service)
{
T remoteDesktopView = new T();
_views.Add(service, remoteDesktopView);
Thread pumpThread = new Thread(() => remoteDesktopView.ShowDialog());
pumpThread.Start();
while (remoteDesktopView.IsHandleCreated == false)
{
//Do not return until the handle has been created!
}
return remoteDesktopView;
}
I do not like this mechanism. I am looking for an elegant solution.
Please take into account that I am coding against an interface. I thought about using a ManualResetEvent or something of the like but having to implement and handle the ManualResetEvent within each Form that implements the interface doesn't sound appealing to me. If you don't agree with me. that's just fine. I merely suspect my current solutions are not the most elegant.
You can add code to a HandleCreated event handler like this:
private void Form1_HandleCreated(object sender, EventArgs e){
//your code
}
The event is not listed in Properties window, you have to register the event handler using code:
HandleCreated += Form1_HandleCreated;
You have to wait for the handle to be created somehow.
So you will end up with something like while (form.IsHandleCreated == false) { ... } somewhere in your code.
The only question is where to put it.
If you do it like in your example above, you need to code the while loop every time you create a form If you choose the alternative you mentioned, using an event raised by the form, you need to implement it in each form (and create an event handler and hook it up).
I don't know if CreateAndShowForm() is a framework method, or something you can change yourself. If you can change it, that's where I would put the waiting. That way you only need to code it once.
Another approach to avoid the code duplication would be handling it in the form, implementing it in your own abstract form base class, and deriving you actual forms from that class. In my opinion, that is complete overkill for this issue - way too much work for very little gain.
If you can't change CreateAndShowForm(), I recommend going with the example above - yes, it definitely isn't elegant, but it gets the work done, the source code is easy to understand, and it doesn't require the additional work of event handling.

XAML C# Function across multiple windows

I've got a program I am working on that has multiple windows. The windows are similar in functionality and I want to have a single event handler to cover a button press event for each window in the application. Is this possible?
If you need to bind a handler in code behind you can encapsulate a handler by delegate and inject into the Windows which are required it.
For instance using Action<T>:
Action<string> commonHandler = (parameter) =>
{
// handler code here
};
class MyWindiow
{
public MyWindiow(Action<string> handler)
{
// store to local and assign to button click
// button.CLick += (o, e) => { handler(parameterToBepassed); }
}
}
I'd look into using a framework to help you out here. My favorite is Prism v4.
If you follow the M-V-VM design pattern you're life will be a lot easier. You'll need to understand Data Binding and DataContext.
That being said, if you decide to go this path, you can bind each of your windows to a command:
<Button Command="{Binding DoFooCommand}" Content="DoFoo"/>
You're ViewModel would have a DelegateCommand member to execute.
public class SomeViewModel : NotificationObject
{
public SomeViewModel()
{
DoFooCommand = new DelegateCommand(ExecuteFoo);
}
public DelegateCommand DoFooCommand { get; set; }
private void ExecuteFoo()
{
//Use the EventAggregator to publish a common event
}
}
And finally, somewhere else in your solution you'll have a code file/class that subscribes to the event and waits for someone to publish the event to process it.
public class SomeOtherPlace
{
public SomeOtherPlace()
{
//Use the EventAggregator to subscribe to the common event
}
public void FooBarMethodToCallWhenEventIsPublished(SomePayload payload)
{
//Do whatever you need to do here...
}
}
I realize some of the things were left out (such as what a "SomePayload" is... look into the EventAggregator information), but I did not want to get into it too much. Just give you a guide on where to go for information and some base code to work off of. If you decide to use the EventAggregator then you'll need to ensure that your subscribing call and publishing calls are utilizing the SAME instance of the EventAggregator. You can do this by looking into MEF. Prism is setup to work with MEF perfectly... I'm not going to lie. Doing all this requires a bit of a learning curve, but it will be worthwhile in the end when you can unit test your ViewModels easily and have your code loosely coupled. The EventAggregator is a great way for different classes to communicate to each other without relying on knowing about each other. And MEF is great for having a Container for your services that you want to utilize across your application.
Hope that gave you a bit of insight on how to go about doing what you want to do on the correct path.

Categories

Resources