Can we broadcast an object to receive in other classes - c#

I have a class named as pendingData with a list of objects and it instantiated with the start of the application and will remain as long as application runs. But I have to change add objects to the list. How can I access that object in other view without passing the object in the constructor?
So, is there a broadcasting method or any way to do that?
And pendingData class is instantiated only once.

To ensure you only get one instance of your object you could use the singleton pattern like this
public class Singleton
{
private static Singleton instance;
private Singleton() {}
public static Singleton Instance
{
get
{
if (instance == null)
{
instance = new Singleton();
}
return instance;
}
}
}
You'll notice the constructor is private so you must obtain an instance through the Instance method. You'll also notice that method only creates an instance of the object if it doesn't exist.
You could use the same Singleton object for all your views knowing that it'll be the same one and therefore the same data.
Alternatively, you could just declare it in a central location, you main window's viewmodel perhaps, and then everything else could access it from there.
As for updating it you could pass a reference to your object to each place that it's used and then update it directly. Or you could do something with events like this
In your view's viewmodel
public static event EventHandler MyEvent;
private void OnMyEvent()
{
if (MyEvent != null)
{
MyEvent(this, new EventArgs());
}
}
In the location where your data object is, perhaps your main window's view model
MyView.MyEvent += delegate
{
// Update your data
};
If you can't have multiple views open and/or don't want your views to respond to data changes once opened then this is probably enough. However, if you want your views to respond to data in real time you could do something with events so one view can tell another view that the data has changed and that it needs to update.

Related

Singleton Property Value is wrong when called from different thread

I have the following Singleton Pattern for the ViewModel of my Options:
private static volatile GeneralOptionsViewModel instance;
private static object syncRoot = new object();
/// <summary>
/// threadsave singleton
/// </summary>
public static GeneralOptionsViewModel Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
instance = new GeneralOptionsViewModel();
}
}
return instance;
}
}
In my XAML I have a color picker from the extended toolkit package:
<xctk:PropertyGridEditorColorPicker Background="Transparent" Name="face"
Margin="5,0" Width="50" BorderBrush="#32FFFFFF" BorderThickness="1"
SelectedColor="{Binding FaceRectColor, Mode=OneWayToSource,
UpdateSourceTrigger=PropertyChanged}"/>
As you can see it is bound to FaceRectColor property of the GeneralOptionsViewModel class which is defined like follows.
Within the setter there is a conversion to MCvScalar (also a property of the same class), the format I later need for my application:
public Color FaceRectColor
{
get
{
return faceRectColor;
}
set
{
if (faceRectColor != value)
{
faceRectColor = value;
FaceRectColorScalar = new MCvScalar(value.B, value.R, value.G, value.A);
SetProperty(ref faceRectColor, value);
}
}
}
My problem now is, that the binding works and also the correct values are written to the variable, however when I call the singleton with the property from a different class - and from a different thread - it always shows zero for all color channels. However, if I break the program directly within the singleton class I can see the correct values. AFAIK the singleton should be threadsafe, so I'm looking for the reason of this behavior.
My guess is some threading issue, since other properties from the singleton class are displayed correctly, but they are only called in the main thread.
Edit: In my case all property values of the singleton class are set before the worker thread is active. This means no changes during the time the worker thread is active.
Edit II: Here is the complete project for code evaluation.
In the class CameraViewModel in line 202 is the relevant call for a function, where I want to pass the values from the singleton.
Your "singleton" contains a public constructor which effectively makes it a non-singleton. And you are not binding to the singleton in your GeneralOptionsView.
If you really want GeneralOptionsViewModel to be a singleton, you should implement it like this:
public sealed class GeneralOptionsViewModel : ViewModelBase
{
private static readonly GeneralOptionsViewModel _instance = new GeneralOptionsViewModel();
private GeneralOptionsViewModel()
{
GetAvailableCameraList();
DetectorTypeList = new List<string>() { "Cascade Detector" };
SelectedDetectorTypeIndex = 0;
}
public static GeneralOptionsViewModel Instance => _instance;
//...
}
You should then set the DataContext of your view to the singleton:
<Grid DataContext="{Binding Source={x:Static local:GeneralOptionsViewModel.Instance}}">
When your property changes and it does so on a different thread, the calls that are made to notify everybody (in particular the UI) of this change are running in the calling thread. Accessing the UI in a thread that is not the UI thread is a bad idea. It might sometimes work. But it will fail sooner or later.
The solution to your current problem is changing the property in the UI thread.
That said, maybe you should think about whether you need a Singleton. That's a huge red flag that something is wrong with the structure of your program. You don't need a Singleton. Nothing bad would happen if some other context had a second settings viewmodel. You seem to want a Singleton because it's so nice and easy to have a global variable. That is the drawback of a Singleton. It's disadvantage that you buy into because you need something from this pattern. If you find you are using this pattern only because it's disadvantage gives you an excuse to have a global variable, you are doing patterns wrong. It's an anti-pattern.

Modifying ViewModel Properties outside of ViewModel - Values aren't saving

Is it possible to modify properties of a ViewModel by using an instance of ViewModelLocator elsewhere in the code? When I try, any value I try to assign seems to be discarded.
For example, a ViewModel, an instance of which named "Game" is contained in my ViewModelLocator. It has a string property named "Test". When I try to modify it this way:
(App.Current.Resources["Locator"] as ViewModelLocator).Game.Test = "Testing";
System.Windows.MessageBox.Show((App.Current.Resources["Locator"] as ViewModelLocator).Game.Test);
or
ViewModelLocator _viewModelLocator = new ViewModelLocator();
_viewModelLocator.Game.Test = "Testing";
System.Windows.MessageBox.Show(_viewModelLocator.Game.Test);
The messageboxes display the value of the string declared in the ViewModel itself if there is one. If a value hasn't been assigned in the ViewModel, the messageboxes show up empty. Either way, they don't display "Testing".
How can I make this work? I'm using MVVM Light with Unity.
public class ViewModelLocator
{
private static Bootstrapper _bootstrapper;
static ViewModelLocator()
{
if (_bootstrapper == null)
_bootstrapper = new Bootstrapper();
}
public GameViewModel Game
{
get { return _bootstrapper.Container.Resolve<GameViewModel>(); }
}
}
public class Bootstrapper
{
public IUnityContainer Container { get; set; }
public Bootstrapper()
{
Container = new UnityContainer();
ConfigureContainer();
}
private void ConfigureContainer()
{
Container.RegisterType<GameViewModel>();
}
}
It looks like this is a problem with Unity. I switched back to MVVM Light's SimpleIoc and it works without a hitch.
When you call Container.RegisterType<GameViewModel>(); this registers the type GameViewModel with the default lifetime manager. The default lifetime manager for the RegisterType method is the TransientLifetimeManager which means that every time Resolve is called a new instance is returned.
So every time the Game property is called a new instance of GameViewModel is returned. Any modifications to the object will only be made to that object (and lost when the object is GC'd). The next time the Game property is called a new instance of GameViewModel is returned.
So, assuming you only want one GameViewModel you should register it as a singleton:
private void ConfigureContainer()
{
Container.RegisterType<GameViewModel>(new ContainerControlledLifetimeManager());
}

Windows Forms, Designer, and Singleton

I'm trying to work with Windows Forms and User Controls and thus far it's been nothing but a headache. I can't make the form or the controls static because the designer doesn't like that and when I use Singleton on my form and controls, the designer still throws errors at me.
My FormMain:
public partial class FormMain : Form
{
private static FormMain inst;
public static FormMain Instance
{
get
{
if (inst == null || inst.IsDisposed)
inst = new FormMain();
return inst;
}
}
private FormMain()
{
inst = this;
InitializeComponent();
}
MainScreen.cs:
public partial class MainScreen : UserControl
{
private static MainScreen inst;
public static MainScreen Instance
{
get
{
if (inst == null || inst.IsDisposed)
inst = new MainScreen();
return inst;
}
}
private MainScreen()
{
inst = this;
InitializeComponent();
}
If the constructor of MainScreen is public the program runs, but when I change it to private I now get an error in FormMain.Designer.cs saying "'Adventurers_of_Wintercrest.UserControls.MainScreen.MainScreen()' is inaccessible due to its protection level". It points to this line:
this.controlMainScreen = new Adventurers_of_Wintercrest.UserControls.MainScreen();
I think this is the instance of the class that the designer makes by default. Should I ditch the designer? Or is there a way around this? Or is there another way to make class properties accessible without using Singleton (since I can't seem to make the form or controls static)? Any help would be greatly appreciated.
You need to keep a reference to each instance of each form if you want to access the public properties of the instantiated form.
One way is to have a class with a static variable for each type of form:
class FormReferenceHolder
{
public static Form1 form1;
public static Form2 form2;
}
This way you would set the static variable whenever you instantiate a form, and then you can access that variable from anywhere in the program. You can go one step further with this and use properties that set up the form if it doesn't already exist:
class FormReferenceHolder
{
private static Form1 form1;
public static Form1 Form1
{
get
{
if (form1 == null) form1 = new Form1();
return form1 ;
}
}
}
...
static void Main()
{
Application.Run(FormReferenceHolder.Form1 );
}
I think I answered a previous question about this, which looks like it is what got you started down this route. The first point is that I wasn't recommending this pattern specifically, just trying to teach you more about how software developers can manage scope.
That said, the problem you are facing isn't insurmountable. You could hobble a public constructor by throwing an exception at runtime and not at design time, for instance, and modify Program.cs to use the static Instance instead of manually constructing the form.
But.
As I said in the other question, the better option would be to change architecture so that you don't need your library code to directly manipulate the GUI in the first place.
You can do this either by just having the GUI ask the library questions when it thinks it needs new data (simple functions) or by letting the GUI be notified when something needs to change. Either method would be better than having the library fiddle with labels directly.
A good place to start would be something like an MVC (model-view-controller) architecture, which I was alluding to in my previous answer. It might be best, though, to give us an idea of what your high-level program structure looks like now on a bit more detail. What are the main classes you are using in your system (not just the ones you've mentioned so far)? What is the main responsibility of each, and where does each live? Then our recommendations could be a little more specific.
EDIT
So, I have mocked up a quick demo of a possible alternative architecture, based on your comment.
I have the following in my project:
FormMain (Form)
TitleScreen (UserControl)
InGameMenu (UserControl)
MainScreen (UserControl)
GameController (Class)
GameModel (Class)
I didn't use Date and LoadSave, for now.
FormMain simply has an instance of each UserControl dropped on it. No special code.
GameController is a singleton (since you tried to use this pattern already and I think it would be helpful for you to try using a working version of it) that responds to user input by manipulating the model. Note well: you don't manipulate the model directly from your GUI (which is the View part of model-view-controller). It exposes an instance of GameModel and has a bunch of methods that let you perform game actions like loading/saving, ending a turn, etc.
GameModel is where all your game state is stored. In this case, that's just a Date and a turn counter (as if this were going to be a turn-based game). The date is a string (in my game world, dates are presented in the format "Eschaton 23, 3834.4"), and each turn is a day.
TitleScreen and InGameMenu each just have one button, for clarity. In theory (not implementation), TitleScreen lets you start a new game and InGameMenu lets you load an existing one.
So with the introductions out of the way, here's the code.
GameModel:
public class GameModel
{
string displayDate = "Eschaton 23, 3834.4 (default value for illustration, never actually used)";
public GameModel()
{
// Initialize to 0 and then increment immediately. This is a hack to start on turn 1 and to have the game
// date be initialized to day 1.
incrementableDayNumber = 0;
IncrementDate();
}
public void PretendToLoadAGame(string gameDate)
{
DisplayDate = gameDate;
incrementableDayNumber = 1;
}
public string DisplayDate
{
get { return displayDate; }
set
{
// set the internal value
displayDate = value;
// notify the View of the change in Date
if (DateChanged != null)
DateChanged(this, EventArgs.Empty);
}
}
public event EventHandler DateChanged;
// use similar techniques to handle other properties, like
int incrementableDayNumber;
public void IncrementDate()
{
incrementableDayNumber++;
DisplayDate = "Eschaton " + incrementableDayNumber + ", 9994.9 (from turn end)";
}
}
Things to note: your model has an event (in this case, just one of type EventHandler; you could create more expressive types of events later, but let's start simple) called DateChanged. This will be fired whenever DisplayDate changes. You can see how that happens when you look at the property definition: the set accessor (which you will NOT call from your GUI) raises the event if anyone is listening. There are also internal fields to store game state and methods which GameController (not your GUI) will call as required.
GameController looks like this:
public class GameController
{
private static GameController instance;
public static GameController Instance
{
get
{
if (instance == null)
instance = new GameController();
return instance;
}
}
private GameController()
{
Model = new GameModel();
}
public void LoadSavedGame(string file)
{
// set all the state as saved from file. Since this could involve initialization
// code that could be shared with LoadNewGame, for instance, you could move this logic
// to a method on the model. Lots of options, as usual in software development.
Model.PretendToLoadAGame("Eschaton 93, 9776.9 (Debug: LoadSavedGame)");
}
public void LoadNewGame()
{
Model.PretendToLoadAGame("Eschaton 12, 9772.3 (Debug: LoadNewGame)");
}
public void SaveGame()
{
// to do
}
// Increment the date
public void EndTurn()
{
Model.IncrementDate();
}
public GameModel Model
{
get;
private set;
}
}
At the top you see the singleton implementation. Then comes the constructor, which makes sure there's always a model around, and methods to load and save games. (In this case I don't change the instance of GameModel even when a new game is loaded. The reason is that GameModel has events and I don't want listeners to have to unwire and rewire them in this simple sample code. You can decide how you want to approach this on your own.) Notice that these methods basically implement all the high-level actions your GUI might need to perform on the game state: load or save a game, end a turn, etc.
Now the rest is easy.
TitleScreen:
public partial class TitleScreen : UserControl
{
public TitleScreen()
{
InitializeComponent();
}
private void btnLoadNew(object sender, EventArgs e)
{
GameController.Instance.LoadNewGame();
}
}
InGameMenu:
public partial class InGameMenu : UserControl
{
public InGameMenu()
{
InitializeComponent();
}
private void btnLoadSaved_Click(object sender, EventArgs e)
{
GameController.Instance.LoadSavedGame("test");
}
}
Notice how these two do nothing but call methods on the Controller. Easy.
public partial class MainScreen : UserControl
{
public MainScreen()
{
InitializeComponent();
GameController.Instance.Model.DateChanged += Model_DateChanged;
lblDate.Text = GameController.Instance.Model.DisplayDate;
}
void Model_DateChanged(object sender, EventArgs e)
{
lblDate.Text = GameController.Instance.Model.DisplayDate;
}
void Instance_CurrentGameChanged(object sender, EventArgs e)
{
throw new NotImplementedException();
}
private void btnEndTurn_Click(object sender, EventArgs e)
{
GameController.Instance.EndTurn();
}
}
This is a little more involved, but not very. The key is, it wires up the DateChanged event on the model. This way it can be notified when the date is incremented. I also implemented another game function (end turn) in a button here.
If you duplicate this and run it, you'll find that the game date is manipulated from lots of places, and the label is always updated properly. Best of all, your controller and model don't actually know anything at all about the View-- not even that it's based on WinForms. You could as easily use those two classes in a Windows Phone or Mono context as anything else.
Does this clarify some of the architecture principles I and others have been trying to explain?
In essence the problem is that when the application runs, it's going to try to instantiate the main form-window. But by using the Singleton pattern, you're essentially forbidding the application from doing that.
Take a look at the sample code here:
http://msdn.microsoft.com/en-us/library/system.windows.forms.application.aspx
You'll notice in particular this section:
[STAThread]
public static void Main()
{
// Start the application.
Application.Run(new Form1());
}
Notice how the program is trying to instantiate Form1. Your code says, nah, I don't really want that since you mark the constructor as private (same holds true for static forms as well). But that's counter to how windows forms is supposed to work. If you want a singleton form-window, just don't make any more. Simple as that.

Performance considerations for event subscription

Consider this code:
class GameEventsManager
{
public void StartGameEvent(GameEvent TheGameEvent)
{
SubscribeToGameEvent(TheGameEvent);
TheGameEvent.Begin();
UnsubscribeToGameEvent(TheGameEvent);
}
private void SubscribeToGameEvent(GameEvent TheGameEvent)
{
TheGameEvent.OnPlaySound += OnPlaySound;
TheGameEvent.OnShowWrittenItem += OnShowWrittenItem;
...
}
private void UnsubscribeToGameEvent(GameEvent TheGameEvent)
{
TheGameEvent.OnPlaySound -= OnPlaySound;
TheGameEvent.OnShowWrittenItem -= OnShowWrittenItem;
...
}
}
A GameEvent is a class that basically does this: when Begin() gets called, it raises events that get passed to the GameEventManager, so that it may "make" the appropriate changes to the game environment (this is by further propagating the events to the objects that are responsible for executing each particular instruction, like in the Observer pattern).
Now take into consideration that all of my InventoryItems (can trigger events, such as OnConsume, OnUse) are static fields in their particular classes. Although this may seem a bit rough around the edges, I feel that being able to do:
AddItem(WrittenItems.NoteFromKing) //NoteFromKing is a static field in WrittenItems
makes things a lot simpler, and it's a welcome sight considering I'm working on a quite complex game.
This, however, makes it very hard for me to list ALL of the game's items somewhere, in case this would be needed. Which brings us to my question:
A LevelManager, that manages things such as when the player interacts with a particular item in the level, tells the GameEventsManager to run a particular GameEvent, if required. The GameEventsManager then subscribes to the GameEvent, starts it, and then unsubscribes. Should I expect to see noticeable performance issues while following this subscribe/run/unsubscribe pattern? In the end, the manager might subscribe/unsubscribe to about 20 events inside GameEvent.
In case the subscribe/unsubscribe mechanism is slow, I could make a single subscribe process that runs at game initialization, but that would force me to build an extra structure, to list all of the items.
So, in short, I'd like to know if I should be expecting considerable slowdowns from this kind of implementation. Or more exactly, if subscribing to about 20 events, and then unsubscribing from them is considerably slow.
Language is C#, using .NET 2.0 subset under Unity 4.
This, however, makes it very hard for me to list ALL of the game's items somewhere
Why so? You could create an ItemManager (which is a singleton):
public class ItemManager
{
private static volatile ItemManager _instance;
private static object syncRoot = new Object();
private ObservableCollection<ItemBase> _registeredItems = new ObservableCollection<ItemBase>();
private ItemManager()
{
}
public ItemManager Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
instance = new ItemManager();
}
}
return instance;
}
}
public void RegisterItem(ItemBase item)
{
_registeredItems.Add(item);
// Do some stuff here, subscribe events, etc.
}
public void UnregisterItem(item)
{
// Do some stuff here, unregister events, etc.
_registeredItems.Remove(item)
}
}
Afterwards you make all item classes derive from a class called "ItemBase". And in ItemBases Constructor you call this:
ItemManager.Instance.RegisterItem(this);
So you don't have to add every single item manually. For more information about the singleton pattern, take a look here: http://msdn.microsoft.com/en-us/library/ff650316.aspx.
A little benefit of this is also, that you can implement a general communication between the GameManager and the ItemManager.

Running a piece of code just once in a class

I need to attach an event handler to an object, and I placed this code on a button click event. However, I noticed that this will cause the same event to attach multiple times with each click.
Is there a way to run a piece of code on class creation? The class in question is a static class btw.
I can do something like:
if (bool == false)
{
attach event handler;
bool = true;
}
Just not sure if this is the right way to do it. Thanks.
There are static constructors, that are (in principle) only run once per class.
Something like this:
public static class MyStaticClass
{
public static int MyStaticProperty;
//no accessors required, as this is never explicitly invoked
static MyStaticClass() //no parameters either
{
MyStaticProperty = 100;
}
}
....
//writes: 100
Console.WriteLine(MyStaticClass.MyStaticProperty);
However, if a constructor won't do it, because you have some parameters that need to be set, or there are some prerequisite steps that need to be done, I would indeed recommend a private boolean check, as you have done.
You use a constructor - it will run on class creation.
Constructors are class methods that are executed when an object of a class or struct is created. They have the same name as the class or struct, and usually initialize the data members of the new object.
For static classes, use static constructors:
A static constructor is used to initialize any static data, or to perform a particular action that needs to be performed once only. It is called automatically before the first instance is created or any static members are referenced.
try
if(Button1.Click == null)
Button1.Click += new System.EventHandler(this.myEventHandler);

Categories

Resources