|
I've spent a lot of time playing with my datagrid control and its associated datatable, and I think I did it all wrong. My scheme is way to complicated. I read a user defined data structure in from a file, then fill out the datagrid from it. Then I track any changes to the datagrid, update the datagrid to reflect these changes (these former two steps are giving me too much trouble, prolly b/c my overlycomplicated design), and then rebuild the structure from these changes. However, there seems to be some interdependencies in the updating of the datagrid that depends upon nonupdated information in the data structure, and it's all a big mess.
My actual on-disk data format is XML, which is then parsed into the datastructure for program specific manipulations (calculating chess scores from a tournament database if you must know). I want my users to be able to create and edit chess tournament databases using this datagrid, which will then be mapped into the in-memory data structure for the calculation and manipulation, and finally saved to a disk in XML format. I have all the XML -> Datastructure and Datastructure -> XML stuff down, but the user input is really getting to me.
So, before I start with my datagrid all over again, I need to know how I'm supposed to do this. My current idea is:
+ Load the file into the data structure
+ Update the datagrid/datatable (I am using them as one, there's only one table).
+ Use the RowChanged event to determine when the datagrid is modified. If so, make those changes INSIDE THE DATA STRUCTURE. Then, after the datastructure is updated, set a flag so that RowChanged does nothing, and rebuild the datagrid from the beginning using the data structure. After it is rebuilt, set the RowChanged flag back so that it responds to user input. I want RowChanged to respond to userinput, but not to respond to itself. I will know this all works when I can throw any valid input into it, and get the same thing out, only now stored in the data structure. When I throw in invalid or incomplete (ie, half a row) input, it should not parse it at all, simply leave it there.
Sound good? There must be a standard way of doing this. I am completely new to all this database stuff.
-Domenic Denicola- [CPUA 0x1337]
MadHamster Creations
"I was born human. But this was an accident of fate - a condition merely of time and place. I believe it's something we have the power to change..."
|
|
|
|
|
I think the recommended way of working with data is through the DataSet.
You can load a dataset from xml (create a schema then specify where to load it from an the schema), then bind the dataset to the datagrid, once you are done editing you should then be able to save the data back to the xml file.
DataSets are a bit mysterious to me though; most of my data access has only been single read/writes so I've not had to worry about that yet
James
Sonork ID: 100.11138 - Hasaki
"Smile your little smile, take some tea with me awhile.
And every day we'll turn another page.
Behind our glass we'll sit and look at our ever-open book,
One brown mouse sitting in a cage."
"One Brown Mouse" from Heavy Horses, Jethro Tull 1978
|
|
|
|
|
A dataset seems to just be a collection of datatables that relate to each other. I only use one data table, and I only want to use it for display and user input purposes. My custom data structure is the best way of storing and manipulating my data, everything is organized for maximum usefulness from the programming side of view. I would like to use the datagrid as a method of directly editing and creating those data structures.
What I am trying to say is, this program is primarily a computation program, not a database program. I have all the code for computation on my data structure and loading into my data structure. I simply want a viable way to display all this data both before and after computation, and also to edit and create new data. DataGrids looked like the solution to my problem, but I dunno, maybe I've stepped too far into the realm of database programming by using them. I JUST WANT USERS TO BE ABLE TO SEE, EDIT, AND CREATE DATA IN A GRID-LIKE FORMAT. I don't want to run a commercial database, or use ADO.NET, or generally have anything to do with the conventional meaning of "database".
Does that help clarify my problem? It is all very confusing, and hard to explain. Sorry if I've just made it worse.
-Domenic Denicola- [CPUA 0x1337]
MadHamster Creations
"I was born human. But this was an accident of fate - a condition merely of time and place. I believe it's something we have the power to change..."
|
|
|
|
|
[edit] bah after re-reading your original post I see I haven't posted anything helpful About the best I can offer would be to let the grid do its job, then when you need the data, pull it from the datagrid all at once (or do it when you add/edit a row). [/edit]
Domenic [CPUA 0x1337] wrote:
A dataset seems to just be a collection of datatables that relate to each other. I only use one data table, and I only want to use it for display and user input purposes.
The power of the dataset is its disconnected nature. The data stored in it is just that data; it doesn't have to come from a database at all. That is one of the strengths of .NET, it uses generic binding rather than forcing the use of ADO.NET or anyother database type technology.
Domenic [CPUA 0x1337] wrote:
DataGrids looked like the solution to my problem, but I dunno, maybe I've stepped too far into the realm of database programming by using them.
After some playing around I think you can do what you need to with a single DataTable (as I think you originally suggested).
Handling the ColumnChanging event lets you determine if a change should be allowed (if you don't want to allow the change throw an exception in the event handler).
Unfortunately I don't see an event that tells you when a new row gets added (and accepted) so you may have a hard time to keep the two in synch at all times but so long as you know when it does/doesn't need to be in synch you can do so by going through the datarow collection on the table.
Thanks for giving me the push to take a deeper look into DataGrids and DataTables
James
Sonork ID: 100.11138 - Hasaki
"Smile your little smile, take some tea with me awhile.
And every day we'll turn another page.
Behind our glass we'll sit and look at our ever-open book,
One brown mouse sitting in a cage."
"One Brown Mouse" from Heavy Horses, Jethro Tull 1978
|
|
|
|
|
James T. Johnson wrote:
Handling the ColumnChanging event lets you determine if a change should be allowed (if you don't want to allow the change throw an exception in the event handler).
Ahhh, so that's what's happening to my current code. It seems after I handle a deletion of a value, whenever I call DataTable.Columns.Remove(...) to reflect the invalidation of the row and update the columns accordingly, my ColumnChanged event handler is never called again. Ah, my code is way too messy anyway, it's prolly a good thing I'm redoing it.
So, does this sound like a good plan? I just iterate through the rows every time columnchanging is called, determine the valid ones, rebuild my data structure using those, and then rebuild my datagrid from my datastructure.
And how to decide between ColumnChanged and ColumnChanging? It seems ColumnChanged is called everytime the cursor moves out of the box or the data is otherwise accepted, which seems more appropriate than ColumnChanging, which is called whenever the column's value changes at all. I dunno, I'll work on it on the weekend when all this homework slows down
-Domenic Denicola- [CPUA 0x1337]
MadHamster Creations
"I was born human. But this was an accident of fate - a condition merely of time and place. I believe it's something we have the power to change..."
|
|
|
|
|
Domenic [CPUA 0x1337] wrote:
Ah, my code is way too messy anyway, it's prolly a good thing I'm redoing it.
If its too messy its probably a good idea Personally I find myself redoing lots of code because it becomes difficult to discern what is going on.
Domenic [CPUA 0x1337] wrote:
So, does this sound like a good plan? I just iterate through the rows every time columnchanging is called, determine the valid ones, rebuild my data structure using those, and then rebuild my datagrid from my datastructure.
Without knowing whats going on its hard to say what would be best. From what I know I would let the datatable do its job then pull the data out of it only when its needed. Handling the ColumnChanging/ColumnChanged events as needed for validation; then run a final validation with the RowChanging event to ensure that fields within a row are ok.
Domenic [CPUA 0x1337] wrote:
And how to decide between ColumnChanged and ColumnChanging?
Here's a quote from the documentation.
The ColumnChanging, RowChanging, and RowDeleting events are raised during the update process. You can use these events to validate data or perform other types of processing. Because the updates are in process during these events, you can cancel the update by throwing an exception, which prevents the change from being completed. For more information, see Data Validation in Datasets.
The ColumnChanged, RowChanged, and RowDeleted events are notification events that are raised when the update has been completed successfully. These events are useful when you want to take further action based on a successful update.
Hopefully you can get some idea where to go from here
James
Sonork ID: 100.11138 - Hasaki
"Smile your little smile, take some tea with me awhile.
And every day we'll turn another page.
Behind our glass we'll sit and look at our ever-open book,
One brown mouse sitting in a cage."
"One Brown Mouse" from Heavy Horses, Jethro Tull 1978
|
|
|
|
|
How to solve "System.StackOverflowException"
I am getting this, when I try to set a value to memeber variable.
namespace StackOverFLow
{
/// <summary>
/// Summary description for Class1.
/// </summary>
class StFlow
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
StFlow STF = new StFlow();
STF.Name = "CodeProject";
string str = STF.Name;
}
public string Name
{
get
{
return Name;
}
set
{
Name = value;
}
}
}
}
Thanks,
Candy
|
|
|
|
|
The problem is caused because your property is trying to get/set itself. You need a private field to store the value, and the property gets/sets that.
private string name;
public string Name {
get {
return name;
}
set {
name = value;
}
} Notice the different in case between name and Name . C# is case sensitive
HTH,
James
Sonork ID: 100.11138 - Hasaki
"Smile your little smile, take some tea with me awhile.
And every day we'll turn another page.
Behind our glass we'll sit and look at our ever-open book,
One brown mouse sitting in a cage."
"One Brown Mouse" from Heavy Horses, Jethro Tull 1978
|
|
|
|
|
Every time you access Name within your getter or setter code, you recursively invoking it. It stops only when this call sequence exhaust the call stack. You can check it tracing execution in debugger. There are to possible ways to correct this. First is to just create the field:
public string Name; // all problems gone
the second one is to back up your property with the private field and use in getter and setter code:
private string name; // lowercase n
public string Name
{
get { return name; } // you are noo more recursively accessing getter here
set { name = value; } // same for setter
}
Cheers,
elk.
|
|
|
|
|
Hi! I'm going to serialize/save an object into a MS SQL Database ... but how?
Hope anybody can help me!!
/Kenneth
|
|
|
|
|
Off the top of my head,
create a binary field in your database, this should be large enough to hold the serialized object; this depends on how many fields/properties the object has (and any sub-objects).
Now create a new memory stream, pass the stream into the binary formatters serialize method to serialize the object to the stream. Now fill the field with the contents of the memory stream.
Object is now serialized in your database
That was my plan for a project where I wanted to do the same thing, but work caught up to me so I never got to implement it.
HTH,
James
Sonork ID: 100.11138 - Hasaki
"Smile your little smile, take some tea with me awhile.
And every day we'll turn another page.
Behind our glass we'll sit and look at our ever-open book,
One brown mouse sitting in a cage."
"One Brown Mouse" from Heavy Horses, Jethro Tull 1978
|
|
|
|
|
bulow_dk e-mailed and asked if I could provide a sample doing what I suggested; I'm posting it here so that others can see how to do it as well.
If you've done binary serialization to a file, doing the same to a database is pretty easy to do, since it just throws in a slight twist.
First create a test class, this is the class that will be serialized to the database.
[Serializable()]
public class TestClass
{
private int foo;
public int Foo
{
get
{
return foo;
}
set
{
foo = value;
}
}
public TestClass()
{
Foo = 0;
}
} Now comes the fun part
public void SaveToDatabase()
{
TestClass foo = new TestClass();
foo.Foo = 3;
MemoryStream memStream = new MemoryStream();
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(memStream, foo);
SqlConnection conn = new SqlConnection( );
SqlCommand cmd = new SqlCommand("AddObject", conn);
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter parm = new SqlParameter("@ObValue", SqlDbType.VarBinary, 8000);
parm.Value = memStream.ToArray();
cmd.Parameters.Add(parm);
conn.Open();
try
{
cmd.ExecuteNonQuery();
}
catch(SqlException ex)
{
MessageBox.Show(ex.Message);
}
finally
{
conn.Close();
memStream.Close();
}
} Following MS' best practices I use a stored procedure to do my database work. The "AddObject" stored procedure accepts a single parameter, a varbinary type with maximum length of 8000 (a little less than 8K of memory).
Now to deserialize the object from the database.
public void LoadObjectFromDatabase()
{
TestClass foo;
long dataSize;
MemoryStream memStream;
BinaryFormatter bf = new BinaryFormatter();
SqlConnection conn = new SqlConnection( );
SqlCommand cmd = new SqlCommand("GetObject", conn);
cmd.CommandType = CommandType.StoredProcedure;
conn.Open();
SqlDataReader dr = cmd.ExecuteReader();
while(dr.Read())
{
dataSize = dr.GetBytes(0, 0, null, 0, 0);
byte [] data = new byte[ dataSize ];
dr.GetBytes(0, 0, data, 0, (int) dataSize);
memStream = new MemoryStream(data);
foo = (TestClass) bf.Deserialize(memStream);
memStream.Close();
}
dr.Close();
conn.Close();
} Again following MS' best practices I use a stored procedure to get the object from the database. It is a simple SELECT on the table returning just the field that contains the object.
Sorry about the lack of spacing, I've posted the sample project on my website where you can read the code more clearly
Sample project
James
Sonork ID: 100.11138 - Hasaki
"Smile your little smile, take some tea with me awhile.
And every day we'll turn another page.
Behind our glass we'll sit and look at our ever-open book,
One brown mouse sitting in a cage."
"One Brown Mouse" from Heavy Horses, Jethro Tull 1978
|
|
|
|
|
Very nice!
Andy Gaskell, MCSD MCDBA
|
|
|
|
|
Does anyone know where can i find a treeview example program?
I am looking for an example that dynamically generate multiple tree level for window application.
Thanks
|
|
|
|
|
try to get code from this book. chapter 13
- Programming C#. by Jesse Liberty
Link for source code is in this web site.
www.libertyassociates.com
|
|
|
|
|
Hi All,
I need to make a SSL connection to a custom server application. I have been searching the .NET docs, but could only find examples using HTTPS.
I know there was a client-server example with the Platform SDK (MFC), but I can't figure out how to do it in .NET
Any hints?
Thanks!
|
|
|
|
|
I want to create my class based on C# class (like Button, Panel or ComboBox). The wizard allows to select a base class only from my classes (not built-in classes). What I'm doing now is create a class based on nothing and then change the declaration of the class (Ex: from class MyClass {} to class MyClass :Panel {}. But my goal is to create visually class.
I also tried to create a class based on UserControl (this gives me opportunity to create visually class), where I can drop controls to this class (btw, UserControl doesn't have Dock and BorderStyle properities). But when I subclass this class again I cannot work visually. I have to do everything in the code.
Is there any way to create visually classes?
(Btw: Why, depending where the cursor is positioned, I getting different interface for creating the class. For example: when the cursor is positioned in the class view and I choose Add New Class from "Project\Add Class.." I'm getting "C# Class Wizard" (which usually crashes) where I can choose a base class. When the cursor is positioned somewhere else I'm getting "Add New Item" wizard where I cannot choose the base class.
Thanks,
Jerzy
|
|
|
|
|
You can't visually design a Control it -- by definition -- is only drawn via OnPaint and you wouldn't gain anything from visually designing because it isn't a container.
A UserControl is what you use if you want to visually design a new control. It is a container that contains other controls. Therefore a visual interface is a nice feature to use (almost required in some cases).
JerzyPeter wrote:
(btw, UserControl doesn't have Dock and BorderStyle properities).
It does have the Dock property since it inherits from Control; all Control's have the Dock property, BorderStyle doesn't exist though.
JerzyPeter wrote:
Btw: Why, depending where the cursor is positioned, I getting different interface for creating the class.
I think this is by design, this has been the case since Beta 2.
Hope I gave you some direction on what you should use for a new control.
If you want to create a class and not a control, create a new class via the the C# Class Wizard then in the class view you should be able to add methods, properties, fields, and indexers (accessing a class instance like an array).
James
Sonork ID: 100.11138 - Hasaki
"Smile your little smile, take some tea with me awhile.
And every day we'll turn another page.
Behind our glass we'll sit and look at our ever-open book,
One brown mouse sitting in a cage."
"One Brown Mouse" from Heavy Horses, Jethro Tull 1978
|
|
|
|
|
Thanks for your answer.
1. UserControl doesn't have Dock property, it has DockPadding which determines the size of the border for docked control.
2. My problem is this: when I create UserControl with bunch of controls (buttons, labels, comboboxes) I want to be able reuse this control and create a subclasses control with extra, for example, 3 buttons, 3 lables and one slider, then I would have to do it in code instead dropping these control on my UserControl.
Anyway, thank you
Jerzy
|
|
|
|
|
JerzyPeter wrote:
1. UserControl doesn't have Dock property
It does have a Dock property, you may be confused as to when you can use it though. The Dock property is used to tell the control where it should position itself on its parent. Thus you can't see it in the property grid while you are designing the UserControl, only when you place the UserControl on a form or another UserControl will you see it.
JerzyPeter wrote:
2. My problem is this: when I create UserControl with bunch of controls (buttons, labels, comboboxes) I want to be able reuse this control and create a subclasses control with extra, for example, 3 buttons, 3 lables and one slider, then I would have to do it in code instead dropping these control on my UserControl.
I've just created a test for this and it worked. However there are some rules that you need to be aware of. When you visually inherit from a Form or a UserControl VS.NET bases the appearance on the latest build available; this can cause problems if you change both the base class and the inherited class without doing a build in-between.
Once you have your base UserControl done the way you would like, build your project/solution; this will create a compiled version of the UserControl so that you can edit the inherited class visually.
Now add another UserControl to your project, open it up in CodeView then change the line that declares your class so that inherits from the UserControl you want to base your new UserControl from. Now you should be able to open the new UserControl up in the VS.NET Forms Designer.
If you want e-mail me and I can post a quick sample showing this done on my website.
HTH,
James
Sonork ID: 100.11138 - Hasaki
"Smile your little smile, take some tea with me awhile.
And every day we'll turn another page.
Behind our glass we'll sit and look at our ever-open book,
One brown mouse sitting in a cage."
"One Brown Mouse" from Heavy Horses, Jethro Tull 1978
|
|
|
|
|
Hi James!
Thank you very much for you answer.
I was really confused with this property Dock (because I didn't see it in design time).
If you don't mind to send me the project I would appreciate very much. (Or just explain how to visually sublcass a UserControl because I think I won't be able to figure out from the project how to do that.)
Thanks, you are a very kind person.
Jerzy
My e-mail: jerzypeter@hotmail.com
|
|
|
|
|
My SMTP server is having problems right now so I'll just post it here.
Sample Project
Here’s what I did to create the sample.
Create a new Windows Application, right click on the project in the solution explorer and choose Add UserControl, call it BaseUserControl.cs.
On the BaseUserControl set the ForeColor to the System palettes Highlight color. Resize the canvas so it is 232x40 pixels. Now add a new label control to it and place it at (8, 8) with the default size. Change the Text on the label to say “base”.
Build the project.
Now Add another UserControl to the project (right click on the project choose Add UserControl). Call it ExtendedUserControl.cs.
Now close the designer for it, right click on ExtendedUserControl in the solution explorer and choose View Code.
Now change the class declaration so that it inherits from BaseUserControl instead of System.Windows.Forms.UserControl.
public class ExtendedUserControl : System.Windows.Forms.UserControl
changes to
public class ExtendedUserControl : BaseUserControl
Build the project again. Now open up the designer for the ExtendedUserControl (double click ExtendedUserControl in the solution explorer).
When you open up the designer for the ExtendedUserControl you should see the BaseUserControl, now add another label placing it at (120, 8) with the default size. Change the Text to read “extended”.
Now click on the background of the UserControl, and set the ForeColor to the System palette’s ControlText color.
Build the project again.
Now open up Form1 by double-clicking on it in the Solution Explorer. In the toolbox you should see two new entries at the bottom; these are the new UserControls you just created. Drag one of each onto the form.
VS.NET will tell you when you make a change that requires a build for you to see it; but to be on the safe side I always do a build.
If you have any other questions feel free to ask.
James
Sonork ID: 100.11138 - Hasaki
"Smile your little smile, take some tea with me awhile.
And every day we'll turn another page.
Behind our glass we'll sit and look at our ever-open book,
One brown mouse sitting in a cage."
"One Brown Mouse" from Heavy Horses, Jethro Tull 1978
|
|
|
|
|
Hi James!
I'm sorry but it doesn't work for me. I did everything as you did (and I was doing the same before). When I double-click ExtendedUserControl in the solution explorer I'm getting an error:
ExtendedUserControl - The base class test.BaseUserControl coud not be loaded. Ensure the assembly has been referenced or built it is part of the project.
Jerzy
|
|
|
|
|
Did you remember to build the project?
That is the error message I get when I forget to do that step.
Give my sample project a try (you'll have to build it before you can view the user controls though).
James
Sonork ID: 100.11138 - Hasaki
"Smile your little smile, take some tea with me awhile.
And every day we'll turn another page.
Behind our glass we'll sit and look at our ever-open book,
One brown mouse sitting in a cage."
"One Brown Mouse" from Heavy Horses, Jethro Tull 1978
|
|
|
|
|
Hi James!
I'm scared to write to you again but belive me it still doesn't work for me. I'm doing exactly the same things as you.
When I open your project I can easily create another subclass of ExtendedUserCotrol.
I don't know what's going on. I tried on different machines with the same result. I was thinking maybe I have different setting in IDE. My Microsoft .NET framework is 1.0 ver. 1.0.3705, Development Environment 2002 ver. 7.0.9466
Thanks
Jerzy
Btw: I found another way of subclassing (but still only in your project): you can 'Add New Item' and choose Inherited Control and select base ExtendedUserControl for example.
|
|
|
|
|