0

I'm working on a plugin application. I have a frmDatasheet.cs (backend) and it's DatasheetPlugin.cs (frontend). I am working on a broadcast event between this datasheet and a model plugin, so that if someone goes back to the datasheet, makes some changes, and then goes back to modeling, modeling will be know of the new state and update itself.

The problem I'm having is the call to Broadcast is in the frmDatasheet, which goes to the datasheetPlugin to Raise the Broadcast Request, and I'm getting nulls because I'm leaving the plugin then coming back to it and everything is lost in that back and forth. Here's my code:

//in the frmDatasheet.cs, click GoToModeling, this is last few lines

IDictionary<string, object> packedState = new Dictionary<string, object>();
packedState = PackState(); <----packs up state to send
frmState.Broadcast(packedState); <----- had to instantiate new Plugin to get at .Broadcast

at the top of frmDataSheet.cs

private DatasheetPlugIn frmState = new DatasheetPlugIn();

Is this possibly the problem?? getting new DatasheetPlugin..does that clear it out, but how else can I get at the .Broadcast?

Here's my code in the DatasheetPlugin.cs

 public void Broadcast(IDictionary<string,object> packedState)
 {
     signaller.RaiseBroadcastRequest(packedState);            
 }

I don't get an error, but the signaller shows the events (BroadcastState, ProjectOpened, ProjectSaved), but they have all null values. Then it goes to the signaller, checks to see if BroadcastState has any subscribers, fails because signaller is null.

How do I ensure that when I get back to the Plugin from the frmDatasheet, everything is still intact? If I put the call to .Broadcast locally in the plugin on some click event, the signaller is not null. So, I'm pretty sure its due to the back and forth and not preserving information.

Update: I should probably include code related to the signaller. Each plugin has:

private VBTools.Signaller signaller;  //declared at top of plugin

//This function imports the signaller from the VBProjectManager
//Happens when app loads for each plugin.
[System.ComponentModel.Composition.Import("Signalling.GetSignaller", AllowDefault = true)]
public Func<VBTools.Signaller> GetSignaller
{
    get;
    set;
}

public void OnImportsSatisfied()
{
//If we've successfully imported a Signaller, then connect its events to our handlers.
signaller = GetSignaller();
signaller.BroadcastState += new VBTools.Signaller.BroadCastEventHandler<VBTools.BroadCastEventArgs>(BroadcastStateListener);
signaller.ProjectSaved += new VBTools.Signaller.SerializationEventHandler<VBTools.SerializationEventArgs>(ProjectSavedListener);
signaller.ProjectOpened += new VBTools.Signaller.SerializationEventHandler<VBTools.SerializationEventArgs>(ProjectOpenedListener);
this.MessageSent += new MessageHandler<VBTools.MessageArgs>(signaller.HandleMessage);
}

Thanks for any insight!!

Tonia Roddick
  • 137
  • 1
  • 3
  • 13
  • Not sure what you mean by "getting nulls". – IngisKahn Jun 15 '12 at 12:59
  • If I hover over signaller in the Broadcast method, I see 5 methods that are in that class but on the right side where the values would be (in the hover box..sorry, I'm not sure of correct terminology), its all nulls. If I have the call inside the same class, get to this line, the right side has {Method = {Void ....}} for each method in the signaller. Wish I knew how to add screenshot images here. – Tonia Roddick Jun 15 '12 at 13:07
  • Was able to add Broadcast to an Interface to allow frmDatasheet to get at method without adding private DatasheetPlugIn frmState = new DatasheetPlugIn(); Thought this would help. Nope. Signaller is still null. Signaller is owned by VBProjectMngr and Imported by each plugin when app loads. But I lose it when i leave class and come back. – Tonia Roddick Jun 15 '12 at 13:49

2 Answers2

0

When you instantiate a new DatasheetPlugin class that has this line:

private VBTools.Signaller signaller;  //declared at top of plugin

The "signaller" object will be null until you instantiate it, which appears you do so when calling OnImportsSatisfied(). So when you say that you are calling...

private DatasheetPlugIn frmState = new DatasheetPlugIn();

...at the top of the file, if you never call "OnImportsSatisfied()" the signaller will be null.

It may be that you are getting confused between class member variables and static variables. http://msdn.microsoft.com/en-us/library/79b3xss3(v=vs.80).aspx

  • I removed the `private DatasheetPlugIn frmState = new DatasheetPlugIn();` and just added the Broadcast() to an interface to let the class know that the method does exist. I know I'm missing something basic dealing with scope and preserving state. It's not just the signaller, its everything in the plugin class that ends up null when I leave it and come back to it from a call. I added code to change the button.enable = true in the Broadcast() to test, and it was also null. – Tonia Roddick Jun 15 '12 at 14:53
  • When you say "come back to it" are you actually creating a new instance of the plugin? Each time you create a new instance the variables inside it will be defaulted. An interface does nothing with state, it just defined a method/property contract that classes need to follow when implementing it. – Tim Sullivan Jun 15 '12 at 14:59
  • When the app loads, each plugin gets loaded. The Datasheet is the active plugin when app finishes loading. There's a DSPlugin.cs and a frmDSheet.cs that work together. The DSPlugin has all the UI stuff:buttons, ribbon along top.., the frmDSheet has all the backend code. When the GoToModeling button is clicked (from DSplugin), code goes to frmDSheet, runs through the code, then calls the Broadcast() sending dict of packedState. The Broadcast() is in the DSPlugin. I'm trying to communicate between 2 classes and preserve DSPlugin's values when I get back to DSPlugin via method call. – Tonia Roddick Jun 15 '12 at 15:15
  • ..Thinking I need to make a constructor in my DSPlugin.. Is it important to mention that I'm using DotSpatial.Controls.Docking on the DSPlugin (all plugins). And working in the 'MEF' with Import/Export signaller for each plugin. – Tonia Roddick Jun 15 '12 at 15:48
0

To solve this problem, I put the GoToModeling click event in the DSPlugin (was in frmDSheet).

void btnGoToModeling_Click(object sender, EventArgs e)
{
    IDictionary<string, object> packedState = new Dictionary<string, object>();
    packedState = _frmDatasheet.PackState();
    Broadcast(packedState);
}

Then the packedState is populated with the current state of the datasheet to be sent to the Broadcast() which is in the same DSPlugin, so I don't lose anything going back and forth between the 2 classes. I took what I needed from the GoToModeling click method in the frmDSheet and moved it up to the PackState so that I can grab that too before broadcasting.

Tonia Roddick
  • 137
  • 1
  • 3
  • 13