The variable is either undeclared or was never assigned - c#

I'm refactoring my code to implement multi-database work. I use System.Data.Common classes and factory to create Exact objects for currently selected database engine. Some connection definitions in Designed looks like:
private System.Data.Common.DbConnection cn;
and assigment is:
private void InitializeComponent()
{
...
this.cn = SqlFactory.CreateConnection();
...
}
and SqlFactory code looks like:
public DbConnection getConnection()
{
return (TSqlConection)Activator.CreateInstance(typeof(TSqlConection));
}
It works okay at runtime, but when i'm trying to open any form in VS Designer i've got errors like the following:
The variable 'cn' is either undeclared or was never assigned.
And Designer can't display form for editing.
How can i fix it?

The InitializeComponent method should not be touched manually in general, the Form Designer always overwrites its contents once you open it. Visual Studio usually adds an autogenerated comment about that in *.Designer.cs. Also, I would suggest not to try to create any DB connection in the default constructor (the one without parameters), because Visual Studio calls it when you attempt to open your form in the Designer.
So, your options are
Create an additional constructor for your form with parameters, this one can try to initialize your DB connection.
Use the Load event of the form.
Create an additional method called, for instance, InitConnections in the form, this method will perform a necessary initialization. You call it right after your form is created somewhere in your code.

Remove this.cn = SqlFactory.CreateConnection(); and everything about cn from Designer.cs.
Add this part after InitializeComponent();.
Now you can edit form and no errors will occurre.

Related

Why can't I use data created in my constructor in Windows Forms?

I am trying to create a Desktop Application that is basically a pet orphanage for people to donate and receive pets without home. I created my database and my design for the app, but my progress is blocked by the fact that whatever variables, parameters or anything I create inside the public : Form2 ( ) constructor cannot be used inside the rest of the code. I have multiple tutorials that I follow for the moment in order to create my application, and all of the use the same approach ( Create database connection inside the constructor of the form, where InitializeComponents() is located, then use that same connection throughout the code ).
I seem to encounter an issue that basically stops me from using anything created inside the constructor ( image below ).
This is stopping me not only with the connection. For example if I create an instance of an User Control like this:
ucHome home1 = new ucHome();
home1.BringToFront();
Everything is working fine and the UC is brought to front but if somewhere in the code ( anywhere ) like a Button-Click function I try to use the method home1.SendToBack() for example the code will not recognize home1 and will tell me it is undeclared.
Any ideas of how I might fix this?
Thank you!
You can pass the sql context at GetData method because actually your context scope is only the constructor.
Try this
private void GetData(MySQLConnection sqlConnection)
{
// Data find
}
Do not forget call GetData method on form2 constructor.

WPF using statement to open another form

I wrote a C# app in Winforms and am now rewriting it in WPF. In the Winforms version I used the following to open another window while sending it information and receive information back from it:
using (showSelection showSelection1 = new showSelection(listBox2.SelectedItem.ToString()))
{
showSelection1.ShowDialog();
storage1.showID = showSelection1.showID;
storage1.numOfSeasons = showSelection1.numOfSeasons;
}
This worked fine, I sent the selected item from listBox2 and received showID and numOfSeasons using this code in the showSelection form:
this.showID = Convert.ToInt32(dataGridView1[2, dataGridView1.CurrentCell.RowIndex].Value);
this.numOfSeasons = dataGridView1[1, dataGridView1.CurrentCell.RowIndex].Value.ToString();
this.Close();
Now, in the WPF version I try the same thing:
using (ShowSelection showSelection = new ShowSelection(showListBox.SelectedItem.ToString()))
{
}
But inside the using( ) I get this error:
ShowSelection: type used in a using statement must be implicitly convertible to 'System.IDisposable'
I'm not really sure where to do from here. Can I fix this and still go about it the same way or is there a different way I should be doing this? The ShowSelection window is just a datagrid with a single button.
WPF components don't use Win32 handles (Window does, but it self-manages), so they have no need to be IDisposable, and you have no need to Dispose them or use them in a using block.
Once there are no more references to your Window it'll be marked for collection by the GC, same as other pure NET components.
In case you want to use it within a using block, you can implement IDisposable on your window manually, but it's indeed not needed.
In case you want to manually remove resources (and keep using it in a using block), then the simplest you can do:
public class ShowSelection : Window, IDisposable
{
public void Dispose()
{
/* here you'd remove any references you don't need */
}
}
But unless there's a need for it, I'd advise against doing so
it's simply says that ShowSelection class do not derive from IDisposable
so use it without the using:
ShowSelection showSelection = new ShowSelection(showListBox.SelectedItem.ToString());
and than access the properties you need to:
showSelection.#####

Visual Studio Text Editor Extension

I am trying to get started in Visual Studio (2010) extensions and I am having a hard time finding the right materials. I have the SDK, but the included samples seem to be things like adorners, windows, and icons.
I am trying to make an extension that will work directly with the text editor (to alphabetize all of my method names in a class, or make all constant names upper case for example) but I can't find a demo for this type of functionality, or even a tutorial.
Does anyone know where I can find this kind of stuff?
I had the exact same question and now have browsed the web several hours until I was being able to understand and explain how you'd need to start with such an extension.
In my following example we will create a small and dumb extension which will always add "Hello" to the beginning of a code file when an edit has been made. It's very basic but should give you an idea how to continue developing this thing.
Be warned: You have to parse the code files completely on your own - Visual Studio does not give you any information about where classes, methods or whatever are and what they contain. That's the biggest hurdle to be taken when doing a code formatting tool and will not be covered in this answer.[*]
For those who skipped to this answer, make sure you downloaded and installed the Visual Studio SDK first or you will not find the project type mentioned in step one.
Creating the project
Start by creating a new project of the type "Visual C# > Extensibility > VSIX Project" (only visible if you selected .NET Framework 4 as the target framework). Please note that you may have to select the "Editor Classifier" project type instead of the "VSIX Project" type to get it working, s. comment below.
After the project has been created, the "source.extension.vsixmanifest" file will be opened, giving you the ability to set up product name, author, version, description, icon and so on. I think this step is pretty self-explaining, you can close the tab now and restore it later by opening the vsixmanifest file.
Creating a listener class to get notified about text editor instance creations
Next, we need to listen whenever a text editor has been created in Visual Studio and bind our code formatting tool to it. A text editor in VS2010 is an instance of IWpfTextView.
Add a new class to our project and name it TextViewCreationListener. This class has to implement the Microsoft.VisualStudio.Text.Editor.IWpfTextViewCreationListener interface. You need to add a reference to Microsoft.VisualStudio.Text.UI.Wpf to your project. The assembly DLL is found in your Visual Studio SDK directory under VisualStudioIntegration\Common\Assemblies\v4.0.
You have to implement the TextViewCreated method of the interface. This method has a parameter specifying the instance of the text editor which has been created. We will create a new code formatting class which this instance is passed to later on.
We need to make the TextViewCreationListener class visible to Visual Studio by specifying the attribute [Export(typeof(IWpfTextViewCreationListener))]. Add a reference to System.ComponentModel.Composition to your project for the Export attribute.
Additionally, we need to specify with which types of files the code formatter should be bound to the text editor. We only like to format code files and not plain text files, so we add the attribute [ContentType("code")] to the listener class. You have to add a reference to Microsoft.VisualStudio.CoreUtility to your project for this.
Also, we only want to change editable code and not the colors or adornments around it (as seen in the example projects), so we add the attribute [TextViewRole(PredefinedTextViewRoles.Editable)] to the class. Again you need a new reference, this time to Microsoft.VisualStudio.Text.UI.
Mark the class as internal sealed. At least that's my recommendation. Now your class should look similar to this:
[ContentType("code")]
[Export(typeof(IWpfTextViewCreationListener))]
[TextViewRole(PredefinedTextViewRoles.Editable)]
internal sealed class TextViewCreationListener : IWpfTextViewCreationListener
{
public void TextViewCreated(IWpfTextView textView)
{
}
}
Creating a class for code formatting
Next, we need a class handling the code formatting logic, sorting methods and so on. Again, in this example it will simply add "Hello" to the start of the file whenever an edit has been made.
Add a new class called Formatter to your project.
Add a constructor which takes one IWpfTextView argument. Remember that we wanted to pass the created editor instance to this formatting class in the TextViewCreated method of our listener class (simply add new Formatter(textView); to the method there).
Save the passed instance in a member variable. It'll become handy when formatting the code later on (e.g. for retrieving the caret position). Also tie up the Changed and PostChanged events of the TextBuffer property of the editor instance:
public Formatter(IWpfTextView view)
{
_view = view;
_view.TextBuffer.Changed += new EventHandler<TextContentChangedEventArgs>(TextBuffer_Changed);
_view.TextBuffer.PostChanged += new EventHandler(TextBuffer_PostChanged);
}
The Changed event is called every time an edit has been made (e.g. typing a char, pasting code or programmatical changes). Because it also reacts on programmatical changes I use a bool determining if our extension or the user / anything else is changing the code at the moment and call my custom FormatCode() method only if our extension is not already editing. Otherwise you'll recursively call this method which would crash Visual Studio:
private void TextBuffer_Changed(object sender, TextContentChangedEventArgs e)
{
if (!_isChangingText)
{
_isChangingText = true;
FormatCode(e);
}
}
We have to reset this bool member variable in the PostChanged event handler again to false.
Let's pass the event args of the Changed event to our custom FormatCode method because they contain what has changed between the last edit and now. Those edits are stored in the array e.Changes of the type INormalizedTextChangeCollection (s. the link at the end of my post for more information about this type). We loop through all those edits and call our custom HandleChange method with the new text which this edit has produced.
private void FormatCode(TextContentChangedEventArgs e)
{
if (e.Changes != null)
{
for (int i = 0; i < e.Changes.Count; i++)
{
HandleChange(e.Changes[0].NewText);
}
}
}
In the HandleChange method we could actually scan for keywords to handle those in a specific way (remember, you have to parse any code on yourself!) - but here we just dumbly add "Hello" to the start of the file for testing purposes. E.g. we have to change the TextBuffer of our editor instance. To do so, we need to create an ITextEdit object with which we can manipulate text and apply it's changes afterwards. The code is pretty self-explaining:
private void HandleChange(string newText)
{
ITextEdit edit = _view.TextBuffer.CreateEdit();
edit.Insert(0, "Hello");
edit.Apply();
}
When compiling this add-in, an experimental hive of Visual Studio starts up with only our extension loaded. Create a new C# file and start typing to see the results.
I hope this gives you some ideas how to continue in this topic. I have to explore it myself now.
I highly recommend the documentation of the text model of the editor on MSDN to get hints about how you could do this and that.
http://msdn.microsoft.com/en-us/library/dd885240.aspx#textmodel
Footnotes
[*] Note that Visual Studio 2015 or newer come with the Rosyln Compiler Platform, which indeed already analyzes C# and VB.NET files for you (and probably other pre-installed languages too) and exposes their hierarchical syntactical structure, but I'm not an expert in this topic yet to give an answer on how to use these new services. The basic progress of starting an editor extension stays the same as described in this answer anyway. Be aware that - if you use these services - you will become dependent on Visual Studio 2015+, and the extension will not work in earlier versions.
just have a look at the "Getting started with Editor extensions" site on the MSDN http://msdn.microsoft.com/en-us/library/dd885122.aspx
Thorsten

Global variable lost which results on failure during function assigning

Currently I'm developing a dashboard for the company that I'm working for. The functionality of this dashboard is not interesting for this problem. This dashboard is build up like:
Asp.net page (with a codebehind ofcourse)
Class where webmethods are defined
Javascript external file (with all the funcitonality of the dashboard, this dashboard works fully clientside)
For the rest I'm working with Visual Studio 2010 Ultimate with a TFS (team foundation server) environment and we make use of the jQuery library and .NET framework 4.0 (C#).
Alright, with that information i hope i can explain my problem. The external javascript file contains three classes. I will name them now ClassMain, ClassSub1, ClassSub2. The classes ClassSub1 and ClassSub2 are derived from ClassMain by doing the following javascript command:
ClassSub1 = new ClassMain();
After this instantiation of the ClassMain other properties and methods of ClassSub1 are loaded. The ClassMain can communicate with the properties and methods of ClassSub1 and ClassSub1 can communicate with ClassMain. So this means that they act like one big class with all kinds of functionality.
I explain this because i think my problem lays here but I'm not sure about it. The classes ClassSub1 and ClassSub2 are getting instantiated in the codebehind of the asp.net page. The following snippet explains it:
StringBuilder javascriptBlockBuilder = new StringBuilder();
javascriptBlockBuilder.AppendFormat("var {0};", this.Id);
javascriptBlockBuilder.AppendFormat("Sys.Application.add_load({0}LoadHandler);", this.Id);
javascriptBlockBuilder.AppendFormat("function {0}LoadHandler() {1}", this.Id, "{");
javascriptBlockBuilder.AppendFormat("{0} = new ClassSub1('{0}');{1}", this.Id, "}");
javascriptBlockBuilder.AppendFormat("var {0};", this.OtherId);
javascriptBlockBuilder.AppendFormat("Sys.Application.add_load({0}LoadHandler);", this.OtherId);
javascriptBlockBuilder.AppendFormat("function {0}LoadHandler() {1}", this.OtherId, "{");
javascriptBlockBuilder.AppendFormat("{0} = new SubClass2('{0}');{1}", this.OtherId, "}");
Page.ClientScript.RegisterStartupScript(this.GetType(), "ClassInitialization", javascriptBlockBuilder.ToString(), true);
In this snippet I create a global variable on the page and assign that class to it. The ClassMain gets the same id as ClassSub1 and ClassSub2 so that they make use of the same variable because like i said a few lines up these classes must act as one class (ClassMain and the ClassSub).
This works also but here comes also the problem. Before executing the above snippet (or after) i have some statements like this:
this.myButton.Attributes.Add("onclick", string.Format("{0}.myJavascriptFunctionality();", this.id));
The functionality gets attached to divisions, buttons, etc.
Ok, now I'm going to render my page and the page loads perfectly, but when I click one of the buttons, divisions, etc. Is it telling me that it requires an object. Somehow my global variables with the ClassSub1 and ClassSub2 are lost and now it can't execute my JavaScript commands.
So my question is, how is it happened that my variables are lost? I hope that my explanation is enough to understand.
It looks like you are calling ClassSub1.myJavascriptFunctionality() in the onclick event of myButton.
ClassSub1 is the function definition / prototype - whatever OOP mechanism you are using. You would have to specify the variable name, not the classname.
like so
this.myButton.Attributes.Add("onclick", String.Format("{0}.myJavascriptFunctionality();", this.Id));
I have found an solution for my problem. The problem occured that my references between the two classes (ClassMain and ClassSub) are referencing to the same variable which results in an error that javascript cannot handle. What did I do to fix this problem?
I have found the answer on this page:
http://www.cristiandarie.ro/asp-ajax/JavaScriptPrototypeInheritance.html
ClassSub1.prototype = ClassMain;
ClassSub1.prototype.constructor = ClassSub1;
And during my construction of the object I did the following call:
ClassMain.call(this, id);
Where 'this' is my current class and I pass an 'id' so that i can reference then to my mainobject.

Selecting one row when working with typed datasets

I have a typed dataset in my project. I would like to populate a datatable with only one row instead of all rows. The selected row must be based on the primary key column. I know I could modify the designer code to achive this functionality however if I change the code in the designer I risk that this code will be deleted when I update my datased via designer in the future.
So I wanted to alter the SelectCommand not in the designer but just before firing up MyTypedTableAdapter.Fill method. The strange thing is that the designer does not create a SelectCommand! It creates all other commands but not this one. If it would create SelectCommand I could alter it in this way:
this.operatorzyTableAdapter.Adapter.SelectCommand.CommandText += " WHERE MyColumn = 1";
It is far from perfection but atleast I would not have to modify the designer's work. unfortunately as I said earlier the SelectCommand is not created. Instead designer creates something like this:
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
private void InitCommandCollection() {
this._commandCollection = new global::System.Data.SqlClient.SqlCommand[1];
this._commandCollection[0] = new global::System.Data.SqlClient.SqlCommand();
this._commandCollection[0].Connection = this.Connection;
this._commandCollection[0].CommandText = "SELECT Ope_OpeID, Ope_Kod, Ope_Haslo, Ope_Imie, Ope_Nazwisko FROM dbo.Operatorzy";
this._commandCollection[0].CommandType = global::System.Data.CommandType.Text;
}
It doesn't make sense in my opinion. Why to create UpdateCommand, InsertCommand and DeleteCommand but do not create SelectCommand? I could bear with this but this._commandCollection is private so I cannot acces it outside of the class code.
I don't know how to get into this collection without changing the designer's code. The idea which I have is to expose the collection via partial class definition. However I want to introduce many typed datasets and I really don't want to create partial class definition for each of them.
Please note that I am using .NET 3.5.
I've found this article about accessing private properties but it concerns .NET 4.0
Thanks for your time.
In the Dataset designer, first configure a Table/Adapter pair with the basic (all rows) query. Make sure it works and updates/deletes etc.
Then right-click, "Add Query" and change the SQL text to include a "WHERE MyId = #Id". Make sure you keep the same columns. Select Next and call the generated method "FillById()".
Ad of course, use FillById(id) instead of Fill() at the right places.

Categories