2

I am working on a UI system for a MonoGame project.

I created one large class called UserInterface. Inside this class, there are nested classes such as Button, Checkbox, Scrollbar, etc. which all inherit from one base class called UIObject. Every object on the UI is stored in a private System.Collections.Generic.List<UIObject> called canvas.

The programmer using this class can easily add a new object to the canvas by using the public method UserInterface.Add(string name, UIObject obj). When the programmer adds an object to the canvas, they assign it a name so that it can be found in the list.

My problem arises as I try to make a public method that will return the object which has a specific name.

My attempt looks likes this:

public UIObject GetObject(string nameOfObject)
{
    return canvas.System.Linq.FirstOrDefault(o => o.Name == nameOfObject);
}

The issue: The object returned by this method is always a UIObject and not the inheriting class that the original object belongs to. That means it can't access the properties of the said original class. For example, if I wanted to check whether or not a Button on the canvas was pressed I would do the following:

UserInterface ui = new UserInterface();
ui.Add("nameOfButton", new Button());

if (ui.GetObject("nameOfButton").IsPressed)
{
    // Do stuff
}

However, this will not work because the property IsPressed belongs to the Button class and the returned object is a UIObject.

How can I return the objects from the canvas using their original type?

SOLVED:
Big thanks to Austin Brunkhorst for pointing me towards generics!

Working method:

public T GetObject<T>(string nameOfObject) where T : UIObject
{
    return canvas.System.Linq.FirstOrDefault(o => o.Name == nameOfObject) as T;
}

Method is called like so:

UserInterface ui = new UserInterface();
ui.Add("nameOfButton", new Button());

if (ui.GetObject<Button>("nameOfButton").IsPressed)
{
    // Do stuff
}    
Community
  • 1
  • 1
GHC
  • 339
  • 4
  • 13
  • Does `if ((ui.GetObject("nameOfButton") as Button).IsPressed)` work for you? – Enigmativity Dec 16 '17 at 05:48
  • Welcome to stack overflow! Thank you for taking the time to articulate your question. – Austin Brunkhorst Dec 16 '17 at 05:52
  • If you found a solution to your problem, please do not put “SOLVED” in your title or add the solution to your question; neither of those things marks the question solved in the UI. Instead, put your solution in the Your Answer box below and click the green checkmark at the upper-left of the answer that best solved your problem. It is OK to mark your own solution as the answer. That marks your question as solved in the UI, and makes it easy for others to find the solution. – Dour High Arch Feb 18 '18 at 16:52
  • @DourHighArch I had already marked a solution with the checkbox. I have seen other reputable users put a solution in their questions before. – GHC Feb 18 '18 at 22:15

1 Answers1

1

You will need to cast the UIObject as the type you're looking to use. In this case, Button.

Button slickButton = (Button)ui.GetObject("nameOfButton");

Careful! This will throw an exception if the object is not in fact a Button.

Alternatively, you can use the as operator, which evaluates to null if the object isn't a Button.

Button slickButton = ui.GetObject("nameOfButton") as Button;

I suggest looking into generics, as you can avoid this by explicitly stating the type you expect and have the method do the magic for you.

Button slickButton = ui.GetObject<Button>("nameOfButton");

Casting Reference

Austin Brunkhorst
  • 20,704
  • 6
  • 47
  • 61