C
C#9mo ago
br4kejet

❔ Accessing the 'current' window from anywhere in the App

My program has multiple windows that can be opened, and each of them have their own notification manager (a view model) Now say for instance some of the windows run a background task every n seconds to perform some operation that could fail (e.g. read from a file). If that operation fails, I want to notify the users that something bad happened. I could use dialogs (so that I don't really need a parent window), but I really want to use that windows' notification manager. But I don't know how I would access that notification manager from anywhere in the code, because some of the functions are very 'generic', like TryReadFile. I could pass the notification manager to each function (that automatically handles errors), but that doesn't feel like good design... Anyone have any ideas?
2 Replies
JakenVeina
JakenVeina9mo ago
it sounds like you're assuming that the notification manager has to live inside the window which is simply not true nor should it be your architecture should look something like this.....
public class MyMainWindowViewModel
{
public MyMainWindowViewModel(MyNotificationManager notificationManager)
{
_notificationManager = notificationManager;

notificationManager.NotificationPublished += (sender, e)
=> urrentNotification = e.Notification;
}
}

public class MyOtherWindowViewModel
{
public MyOtherWindowViewModel(MyNotificationManager notificationManager)
{
_notificationManager = notificationManager;
}

private void OnBackgroundTaskRequested()
{
SpawnBackgroundTask(() =>
{
...
_notificationManager.PublishNotification(...);
}
}
}

public static class EntryPoint
{
public static void Main()
{
var notificationManager = new NotificationManager();

var mainWindow = new Window()
{
.DataContext = new MyMainWindowViewModel(notificationManager)
};
mainWindow.Show();

var otherWindow = new Window()
{
.DataContext = new MyOtherWindowViewModel(notificationManager)
};
otherWindow.Show();

mainWindow.WaitUntilClosed();

if (otherWindow.IsOpen)
otherWindow.Close();
}
}
public class MyMainWindowViewModel
{
public MyMainWindowViewModel(MyNotificationManager notificationManager)
{
_notificationManager = notificationManager;

notificationManager.NotificationPublished += (sender, e)
=> urrentNotification = e.Notification;
}
}

public class MyOtherWindowViewModel
{
public MyOtherWindowViewModel(MyNotificationManager notificationManager)
{
_notificationManager = notificationManager;
}

private void OnBackgroundTaskRequested()
{
SpawnBackgroundTask(() =>
{
...
_notificationManager.PublishNotification(...);
}
}
}

public static class EntryPoint
{
public static void Main()
{
var notificationManager = new NotificationManager();

var mainWindow = new Window()
{
.DataContext = new MyMainWindowViewModel(notificationManager)
};
mainWindow.Show();

var otherWindow = new Window()
{
.DataContext = new MyOtherWindowViewModel(notificationManager)
};
otherWindow.Show();

mainWindow.WaitUntilClosed();

if (otherWindow.IsOpen)
otherWindow.Close();
}
}
I could pass the notification manager to each function (that automatically handles errors), but that doesn't feel like good design
it's a standard-enough design that there's a term for it: Dependency Injection although, in C#, dependencies are usually injected via constructor, not via method parameter depends on what your specific code looks like
Accord
Accord9mo ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.