Call System.IDisposable.Dispose on object 'cboUltra' before all references to it are out of scope - vb.net

when I try to run the below code i'm getting the error through code analysis.
//Code
For Each UltraGridRow In transactionFieldsGrid.Rows.GetAllNonGroupByRows()
If (Field.FieldTypeId = 1000) Then
Dim cboUltra = New UltraCombo()
cboUltra.DataSource = LoadLookupMulticolumn(Field.LookUpCode)
UltraGridRow.Cells("FieldValue").ValueList = cboUltra
EndIf
Next
//Error
CA2000 Dispose objects before losing scope In method 'TransactionFieldsController.LoadTransactionFieldsGrid(UltraGridBase, Collection(Of TransactionField), WorkflowsController, Boolean)', object 'cboUltra' is not disposed along all exception paths. Call System.IDisposable.Dispose on object 'cboUltra' before all references to it are out of scope.
To overcome this I rewritten the code as:
For Each UltraGridRow In transactionFieldsGrid.Rows.GetAllNonGroupByRows()
If (Field.FieldTypeId = 1000) Then
Using cboUltra As New UltraCombo()
cboUltra.DataSource = LoadLookupMulticolumn(Field.LookUpCode)
UltraGridRow.Cells("FieldValue").ValueList = cboUltra
End Using
EndIf
Next
But when I tried like the above code. I'm getting an Object reference error when the below line gets executed.
transactionFieldsGrid.ActiveRow = transactionFieldsGrid.Rows.GetRowAtVisibleIndex(0)
Note: The grid and rows contain values.
Any solutions?

In this case, you can't dispose the UltraCombo instances in the method because the grid has references to the UltraCombo. For disposing the UltraCombo's that you are creating, you would need to store them in a collection scoped to the form and dispose them when the form is disposed. This is necessary because within the method is too soon since the grid still needs access to the combo.
Note that if you need to use the same data for multiple drop downs in the grid, then it would be better to only have one instance of that drop down and reuse it. For this you could create a helper object that would track the instances of the UltraCombo and return the correct instance for a specific LookUpCode and if it hasn't already created the instance it would when it is requested. If these are stored in a dictionary in the helper object, you could implement IDisposable on the helper and dispose all of the UltraCombos when dispose is called on the helper. You could then have a single instance of this helper on your form and call its dispose when the form is disposed.

Related

Duplicated Control Name Causing 'Not A Member' Compile Errors

I have created a custom control called MultiTextbox. When I place my control onto a form and try to run my project, I get the following errors:
'MultiTextBox' is not a member of 'MultiTextbox.MultiTextbox'.
Type 'MultiTextbox.MultiTextbox' is not defined.
In my Form1.Designer code, I can see the following issues:
Me.MultiTextbox1 = New MultiTextbox.MultiTextbox()
Me.MultiTextbox1.ObjectAlignment = MultiTextbox.MultiTextbox.ObjectPlacement.Left
Me.MultiTextbox1.Style = MultiTextbox.MultiTextbox.TextboxStyle.Normal
Friend WithEvents MultiTextbox1 As MultiTextbox.MultiTextbox
I don't understand why it is duplicating the Control name for a selected few items.
The properties it is referring to are custom properties based from Enums.
For example:
Public Enum ObjectPlacement
Left
Right
End Enum
Private m_ObjectAlignment As ObjectPlacement = ObjectPlacement.Left
'ObjectAlignment
<Browsable(True), Category("Appearance"), _
Description("The text to display as an input group header.")> _
Public Property ObjectAlignment As ObjectPlacement
Get
Return m_ObjectAlignment
End Get
Set(value As ObjectPlacement)
If m_ObjectAlignment = value Then Return
m_ObjectAlignment = value
Me.Invalidate()
End Set
End Property
UPDATE
If I place my custom control on a form and run, everything will work fine without error, but as soon as I modify my control in any way (e.g. Size, Style, etc.) it gives me errors, and I can't even run the application as the compiler just sits in an infinite loop saying 'Building...'. I have to force quit VS.
Okay, after some useful posts on this thread and some googling, I found that by removing the Root Namespace from my project it removed all of my compiler errors that I was getting regarding a duplicated namespace (MultiTextbox.MultiTextbox):
Me.MultiTextbox1 = New MultiTextbox.MultiTextbox()
Me.MultiTextbox1.ObjectAlignment = MultiTextbox.MultiTextbox.ObjectPlacement.Left
Me.MultiTextbox1.Style = MultiTextbox.MultiTextbox.TextboxStyle.Normal
Friend WithEvents MultiTextbox1 As MultiTextbox.MultiTextbox
Secondly, the lockups that I was experiencing when trying to build my project was due to me setting a button's visible state within my paint event causing an infinite refresh loop of my control.

Invoking Method of Presenter on Activation

I'm using Smart Client Software Factory 2008. In the module controller, I have code that creates a new child controller only if it hasn't been created, by doing something like the following:
Dim key = "Item-" + item.ID.ToString()
Dim childWorkItem = Me.WorkItem.WorkItems.Get(Of ControlledWorkItem(Of ItemWorkItemController))(key)
If childWorkItem Is Nothing Then
childWorkItem = Me.WorkItem.WorkItems.AddNew(Of ControlledWorkItem(Of ItemWorkItemController))(key)
Else
childWorkItem.Activate()
End If
Multiple items reuse the same key, so when that action is triggered, it shows the tab instead of creating a new instance of it. This works great.
However, there is one drawback. Once activated, I need to run a check within that item's presenter. So I need to call a method on the presenter. Is there a way to invoka a method on the presenter, or is there an event that runs on the view when the work item is activated? I'm not sure how to make that happen?
Thanks.
If you are using a Smart Part as your View you should be able to accomplish this using the IWorkspace.SmartPartActivated event.
This is how I have it setup in my project. I apologize, my code is all in C# but you should be able to apply it in VB relatively easily.
The WorkItemController class has the Activate method setup like this
ISmartPartView _smartPartView
public void Activate()
{
IWorkspace contentWorkspace = this.WorkItem.Workspaces[WorkspaceNames.ShellContentWorkspace];
contentWorkspace.Activate(_smartPartView);
WorkItem.Activate();
}
In the ISmartPartView Presenter class you should be able to create a handler for the SmartPartActivated event like this:
IWorkspace contentWorkspace = this.WorkItem.Workspaces[WorkspaceNames.ShellContentWorkspace];
contentWorkspace.SmartPartActivated += workSpaceSmartPart_ActivatedHandler;
In the workSpaceSmartPart_ActivatedHandler event handler, you can check the SmartPart being activated and if its your ISmartPartView class you can run the desired code.

Error returning objects to VBA from Visual Foxpro COM server

I am getting the following message when trying to return a new object to VBA from my Visual Foxpro COM server.
"Run-time error '-2147417851 (80010105)':
Method 'ReturnObject' of object 'Itestclass' failed"
If I remove the "Dim ... As" line the error goes away but then I lose intellisense for the COM object.
This is the VBA code:
Sub Test()
'' Removing the following line gets rid of the error but loses intellisense for the COM object
Dim objTest As testcom.TestClass
Set objTest = CreateObject("TestCOM.TestClass")
Set objNew = objTest.ReturnObject '' This is the line that causes the error
End Sub
I have created a link to the TestCOM type library in Tools > References
Here is the Visual Foxpro (VFP) code:
The COM server is being built as an out of process EXE. If I build it as an inprocess .DLL then the VBA code causes Excel to crash.
DEFINE CLASS ObjectToReturn AS SESSION OLEPUBLIC
ENDDEFINE
DEFINE CLASS TestClass AS SESSION OLEPUBLIC
FUNCTION ReturnObject
RETURN CREATEOBJECT("ObjectToReturn")
ENDFUNC
ENDDEFINE
I have tried changing the RETURN CREATEOBJECT("ObjectToReturn") to RETURN CREATEOBJECT("CUSTOM") but the problem persists.
Please advise how I can get rid of this error without losing the intellisense for the COM object in VBA. Thanks
I don't know why you are going through such difficulties... This should be able to help you... You can define your class as OlePublic and set some properties on it like the samples at the top. You can set these properties anywhere through the other functions that are not HIDDEN.
If you need to are trying to get at certain elements OF some other "object", try creating an instance of the object and stick it into a property on the OlePublic class... see my method
DoSomethingElse
which does a simple scatter NAME call to the "SomeObject" property of the class. Even though you are not explicitly returning it, it should be visible from within your creation of it from VB...
DEFINE CLASS VFPClassForVB as Session OLEPublic
cTmpFiles = ""
cCOMUser = ""
SomeObject = ""
FUNCTION Init()
*/ Who is user... always ignore the machine....
This.cCOMUser = SUBSTR( SYS(0), AT( "#", SYS(0)) +1 )
This.cTmpFiles = "somepath\"
*/ Unattended mode... any "MODAL" type dialog will throw error / exception
SYS(2335, 0 )
*/ ALWAYS HAVE EXCLUSIVE OFF FOR COM!!!
SET EXCLUSIVE OFF
*/ ALWAYS HIDE DELETED RECORDS!!!
SET DELETED ON
ENDFUNC
*/ Error handler at the CLASS level will always be invoked
*/ instead of explicit ON ERROR or TRY/CATCH handlers...
FUNCTION xError(nError, cMethod, nLine)
lcMsg = "User: " + SYS(0) + " Tmp:" + SYS(2023);
+ " Method: " + cMethod + " Error: " + STR( nError,5);
+ " Line: " + STR( nLine, 6 )
STRTOFILE( lcMsg, This.cTmpFiles + "COMLog.txt" )
*/ NOW, throw the COM Error...
COMReturnError( cMethod + ' Error:' + str(nError,5);
+ ' Line:' + str(nline,6);
+ ' Msg:' + message(), _VFP.ServerName )
RETURN
HIDDEN FUNCTION SomeOtherFunction( lcWhat String,;
lnThing as Integer ) as String
*/ Do something
RETURN 1
ENDFUNC
*/ Another completely visible function direct form VB
FUNCTION DoSomethingElse( SomeParameter as String ) as String
USE SomeTable
*/ Now, this object should be visible as a direct property in VB
SCATTER MEMO NAME This.SomeObject
ENDFUNC
ENDDEFINE
Your VB side, even from your sample...
Sub Test()
Set objTest = CreateObject("MySampleProject.VFPClassForVB")
objTest.DoSomethingElse( "I dont care" )
dim Something as objTest.SomeObject.ColumnFromTable
End Sub
You can create as many OlePublic classes in your in-code class libraries that you want to expose and just create those instances as needed. Let me know if this helps you get closer and we'll try to keep working it out.
I've tried all sorts of samples, but looking at what you have of the object where both are VFP OleObject entries, each is exposed, and can be created individually. You don't need to create one to create the other.
Is there some reason SPECIFIC you are trying to create one object from another? You can have one object expose a bunch of methods and properties to perform whatever you need from VFP.
If you want to have multiple object classes exposed, and under a central control, you can always create your primary object for communication and have IT create an instance of each "other" class on it. Then, expose methods on your main class to handle the communications between them to act out whatever it is you need.

How do I check whether a Linq-to-SQL object is already attached to a DataContext?

I have an object that may have been inflated via a plain old DataContext, or may just have been new-ed up with just its .ID property set. There's no way to know for sure. I'm looking to rehydrate the entire object from whatever is in the database. If the object was new-ed up, I can call .Attach() on the table object and refresh from the Data Context with no trouble. But, if the object was already inflated from the DataContext I get the error: "Cannot attach an entity that already exists.". There's no timestamp field or anything like that - just an integer primary key being used to control the rehydration. I'd like to know if there's a way to conditionally attach. Here's the code - it works the way I want it to, but this seems a hackish way to go about it:
' myDC is a shared instance of a vanilla DataContext...
' myObj is an instance of a linqed-up `SomeLinqObject`
Dim tbl = myDC.GetTable(Of SomeLinqObject)()
Try
tbl.Attach(myObj) ' <-- Wish I could just TryAttach() here!
Catch ex As Exception
If ex.Message = "Cannot attach an entity that already exists." Then
' Do nothing
Else
Throw
End If
End Try
myDC.Refresh(RefreshMode.OverwriteCurrentValues, myObj) ' Rehydrate
-- EDIT --
Thanks to Isaac's answer, here's the revised code:
Dim tbl = myDC.GetTable(Of SomeLinqObject)()
Dim isAttached = (tbl.GetOriginalEntityState(myObj) IsNot Nothing)
If Not isAttached Then tbl.Attach(myObj)
myDC.Refresh(RefreshMode.OverwriteCurrentValues, myObj) ' Rehydrate
GetOriginalEntityState(T entity) on Table -might- be what you're looking for. If you pass it an entity that you've loaded from the context, it returns the original version of the entity held in the context. If you pass it a new entity (or I believe one simply not sourced from that context), it returns null.
var context = new DataClasses1DataContext();
var person = context.Person.First();
var isAttachedToContext = context.Person.GetOriginalEntityState(person) != null; // returns true
var isNewEntityAttachedToContext = context.Peoples.GetOriginalEntityState(new Person()) != null; // returns false
Apologies - answer is in C# but I hope you get the gist!

Adding content to silver light controls from database using wcf ria services

I am trying to retrieve strings from the database and add it as content to the controls on my page before it loads(somewhat like a custom localization). I retrieve my strings from the database uing ria services as follows:
**
Web.DomainService1 context = new Web.DomainService1();
LoadOperation<Web.LocalizationTab>LoadOp=context.Load(context.GetLocalizationTabsQuery(currentCulture, moduleName));
Dictionary<string, string> localizationDictonary = new Dictionary<string, string>();
List<Web.LocalizationTab> localList = new List<Web.LocalizationTab>();
LoadOp.Completed += (s, e) =>
{
localList = LoadOp.Entities.ToList<Web.LocalizationTab>();
//System.Windows.MessageBox.Show(localList.Count.ToString());
foreach (Web.LocalizationTab item in localList)
{
// var control = this.FindName(item.Control_ID.ToString());
if (!localizationDictonary.ContainsKey(item.Control_ID))
{
localizationDictonary.Add(item.Control_ID, item.Control_Text);
}
}
};**
This piece of code is in a separate class called utilities.cs.
now in my Mainpage.xaml.cs i need to get this dictionary with values and then set the controls with the strings from the dictionary.
my problem is that when i do the following in the constructor of Mainpage.xaml.cs:
utilities.getDict(ModuleName);
button1.Content = localizationDictonary["button1"].ToString();
i get an exception as the dictionary doesnt contain values at that point of time.. The load completed event of getting data from the database gets fired only after my constructor is exited. now how do i go about setting my controls automatically in this particular scenario??
Try loading your dictionary in the Silverlight Application class StartUp event. This should ensure that your Dictionary is loaded (and could be placed in the Application Resources for retrieval elsewhere in your application).
You'll need to wait for the GetLocalizationTabsQuery to complete before instantiating your MainPage. In your App.xaml.cs file, you can start the query, add a query completed handler, and only create the MainPage when the query completed handler gets called.