1

My program has network functionality so to avoid messagebox spam in case of network problem i display errors from a collection.

internal class VM_Main
    {   ...
        public ObservableCollection<string> Errors { get; } = new observableCollection<string>();
        ...
    }

This collection is displayed in my XAML window.

public MainWindow()
    {    ...
        vm_Main = new VM_Main();
        dgdErrors.ItemsSource = vm_Main.Errors;
        ...
    }

This is OK.

My problem is when i use objects from other classes in variables. How can I send information to the errors collection to report an error?

internal class VM_Main
{   ...
    public ObservableCollection<string> Errors { get; } = new observableCollection<string>();
    ...
    List <Customers> allCustomers = new List<Customer>()
}

public class Customer
{   ...
    public string Name { get; set; }
    ...
    public Customer()
    {
        try{ // Network work }
        catch (Exception ex) {   ????? Errors.Add(ex.Message) ????  }
    }
    ...
}

"Errors doesn't exist in the current context." Of course, but how am I supposed to do ?

Eldora248
  • 25
  • 4
  • Try this => [HERE](https://stackoverflow.com/questions/793100/globally-catch-exceptions-in-a-wpf-application) for set globally catch – Mehdi Kacim Sep 02 '22 at 12:54
  • I don't know what framework you are using, nor the version or options, but normally you would use Dependency Injection and add an `ILogger` to every place you need it. Then you can log with `Severity.Error`. Read [Logging in .NET Core and ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/logging/). Of course you can make your own `ErrorService`, if you really want full control, but think about how the experienced people at Microsoft have solved such things for you. – JHBonarius Sep 02 '22 at 13:05
  • @JHBonarius I'm using c# with .NET Framework 4.7.2. There is something pre-built for this kind of situation ? – Eldora248 Sep 02 '22 at 14:17
  • You could use a logger package like Serilog or log4net. [look here for an example](https://github.com/rishabhverma17/WPF-Logger) – JHBonarius Sep 02 '22 at 14:32

2 Answers2

1

Here is a fully OOP implementation design using singleton pattern (lazy approach). Further info Singleton pattern

1- Define the singleton class.

using System;
using System.Collections.ObjectModel;

namespace ErrorToConsole
{
    public sealed class Singleton
    {
        private ObservableCollection<String> Errors = new ObservableCollection<string>();

        private static readonly Lazy<Singleton> lazy = new Lazy<Singleton>(() => new Singleton());

        public static Singleton Instance { get { return lazy.Value; } }

        private Singleton()
        {

        }

        public string AddError(string strError)
        {
            Errors.Add(strError);
            return strError;
        }

        public ObservableCollection<string> GetErrors()
        {
            return Errors;
        }

    }

}

2- Calling the singleton class to add and retrieve errors.

using System;

namespace ErrorToConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            var singleton = Singleton.Instance;

            try
            {
                
                //Adding some errors here
                singleton.AddError("aaa");
                singleton.AddError("bbb");
                singleton.AddError("ccc");
                singleton.AddError("ddd");

                throw new Exception("Throwing exception");
            }

            catch (Exception ex)
            {
                //Adding exception message here
                singleton.AddError(ex.Message);

                //this is just to show that all the errors where added to the singleton collection.
                foreach (var val in singleton.GetErrors())
                {
                    Console.WriteLine(val);
                }
                Console.ReadLine();
            }
        }
    }
}
jmvcollaborator
  • 2,141
  • 1
  • 6
  • 17
1

You make an interface:

public interface IErrorReport
{
    void AddError(string message);
}

You then let your main window implement that interface:

internal class VM_Main : IErrorReport
{
    ...
    public void AddError(string)
    {
        Errors.Add(string);
    }
}

In your Customer constructor you add a parameter:

public Customer(IErrorReport report)
{
    try
    { 
        // Network work 
    }
    catch (Exception ex) 
    {   
        Report.AddError(ex.Message);
    }
}

Then all you need is to pass a reference to the main window when you create the customer:

internal class VM_Main
{   ...
    public ObservableCollection<string> Errors { get; } = new observableCollection<string>();
    ...
    List <Customers> allCustomers = new List<Customer>(this);
}
Palle Due
  • 5,929
  • 4
  • 17
  • 32
  • this approach works as well, but imho does not make sense to add the interface implementation everywhere and make a constructor with one parameter related to errors. – jmvcollaborator Sep 02 '22 at 13:04
  • You only make the implementation once. Only the mainview needs to know how to add an error, other classes just need to know an interface that can do it for them. – Palle Due Sep 02 '22 at 13:06
  • Have a look at IProgress which is sort of the same methodology: https://learn.microsoft.com/en-us/dotnet/api/system.iprogress-1?view=net-6.0. – Palle Due Sep 02 '22 at 13:07
  • The interface also makes it easier to write unit tests, because you can mock it or write a simple implementation of it. A singleton will make it harder to unit test. – Palle Due Sep 02 '22 at 13:09
  • Thanks ! But what if Customers have an other collection and I need to send error from this deeper object ? – Eldora248 Sep 02 '22 at 13:13
  • Just store the IErrorReport reference in Customer and pass it on to the other classes that need it. – Palle Due Sep 02 '22 at 13:20
  • @PalleDue "store the IErrorReport reference and pass it" that be big problem if you have many class need it and you need write it in evey single class. you will be crazy. so some times "static" class or "singleton" it's not a bad idea. – TimChang Sep 05 '22 at 01:47
  • See https://stackoverflow.com/questions/137975/what-are-drawbacks-or-disadvantages-of-singleton-pattern for a discussion of the pro's and con's of the singleton pattern. The solution I have sketched is quite simple and straightforward. If something more advanced was required, I would prefer to use IOC, rather than a singleton. – Palle Due Sep 05 '22 at 06:59