|
You might be able to do that sort of thing with a DataGridView.
But, personally, I find it to be a rather poor design. I would prefer that the "Add Person" button brought up a dialog. One benefit of this is that the user can cancel the entry without affecting the form (I assume that the way you described would require removing the added controls).
How you display the list of "people's Name and their State and City" would likely need to change as well -- I would probably use a TreeView rather than a bunch of TextBoxes and ComboBoxes.
|
|
|
|
|
How I'd do this is:
- Maintain a list of data objects, containing the data you want:
class Person : BaseNotifier {
private string name;
public string Name { get { return name; } set { name = value; Notify('Name'); } }
private string state;
public string State { get { return state; } set { state = value; Notify('State'); } }
}
(BaseNotifier is a simple implementation of INotifyPropertyChanged, see end of post), and in your main class:
List<Person> people = new List<Person>();
- Create a custom control that can be bound to a person:
class PersonPanel : Panel, INotifyPropertyChanged {
TextBox nameTextBox;
ComboBox stateCombo;
public static readonly string[] States = { "NSW", "SA", "WA", "NT", "ACT", "TAS" };
public PersonPanel(){
Width = 200;
Height = 30;
Controls.Add(nameTextBox = new TextBox());
nameTextBox.Left = nameTextBox.Top = 5;
nameTextBox.TextChanged += (s, e) => Notify("Name");
stateCombo.SelectedIndexChanged += (s, e) => Notify("State");
}
public string Name {
get { return nameTextBox.Text; }
set { nameTextBox.Text = value; }
}
public string State {
get { return (string)stateCombo.SelectedItem; }
set { stateCombo.SelectedItem = value; }
}
public event PropertyChangedEventHandler PropertyChanged;
private void Notify(string property){
PropertyChangedEventHandler h = PropertyChanged;
if(null != h) h(this, new PropertyChangedEventArgs(property));
}
}
The notification is so two way data binding can work.
- When you add a new person, create and bind one of these to a new Person object
void AddNewPerson(){
Person person = new Person();
if(people.Count > 0) person.State = people[people.Count - 1].State;
people.Add(person);
PersonPanel panel = new PersonPanel();
panel.DataBindings.Add("Name", person, "Name");
panel.DataBindings.Add("State", person, "State");
Panel.Controls.Add(panel);
}
This gives you a nice separation of the data part and the UI, allowing you to change view driver or easily store the data in a database or file system.
BaseNotifier is a simple implementation of INotifyPropertyChanged to avoid typing the same thing several times:
public abstract class BaseNotifier : INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged;
protected void Notify(string property){
PropertyChangedEventHandler h = PropertyChanged;
if(null != h) h(this, new PropertyChangedEventArgs(property));
}
}
|
|
|
|
|
If you are going with this approach and the dynamic controls are the same for each new 'row' then it would be easiest to create a new control that contains the dynamic controls and their logic (essentially 'Panel' in your above code but as a distinct control)
That way you can have your new control fire events, when a new control is added you can have the other controls hook up to its events and react accordingly
Pedis ex oris
Quidquid latine dictum sit, altum sonatur
|
|
|
|
|
You already have three excellent answers from PieBaldConsult, BobJanova, and GParkings that each give you valuable insights, and strategies.
While I'm not sure why PieBaldConsult why considers a DataGridView a "poor design" in this particular scenario: and, I have to confess my bias: I just hate the DataGridView, and think it's an ugly thing, so in that sense I certainly agree you should not use it. I also like PBC's idea of using a dialog (or pop-up Form) which gives the user the option to Cancel, before automatically adding another "virtual row of Controls" to your Panel.
If you automatically add a new 'Person object, and the user decides they really didn't want to do that: what do you do now: can the user delete a selected 'Person object: if so, how ?
But, the larger question I have about your design here is what appears to be the absence of your using a database to write and store, at some point, the collection of 'Person objects. You already use database tables for State/City correlations. Can we assume that, at some point, you are going to enumerate the list of 'Person objects and write them to a database ?
And, I'd like to respond to your question exactly as asked: your code shows you are creating three new controls, with each addition of a new user, and adding them to the Panel.
A better strategy, imho, is to create a UserControl that has all three controls, and add a new one of those with each click of the 'Add Person' button to the Panel: by using docking properly, and setting z-order, they'll form an ordered list, naturally, and you can set scrollbars in the Panel to visible for easy access to the whole list, should it overflow the Panel bounds.
Note that using UserControls would handle the problem of deleting entries easily: since you can maintain a "currently selected 'Person instance" variable that contains a reference to the UserControl that currently has "Focus."
Within the UserControl, you can have a public property for each of the three Controls, whose value is set to the instance of the Control, in the UserControl 'Load event, and thus are easily accessible from your Panel, or its containing Form. Or, for more limited exposure (parsimony): have the three public properties be only the text value of the UserName control, and the ComboBox Index properties of the State and City objects.
imho, Events come into play here when someone changes their choices for values in the three "field entry" facilities. And, imho, Bob Janova, covers that exhaustively in his answer. I've had such a negative experience using PropertyNotification in WinForms, that I'd handle this by invoking static methods in a static class to update, but perhaps my thorough study of Bob's example ... which is going to happen ... will straighten my head out about PropertyNotification, and I'll have a "conversion experience"
The question of how the newly created 'Person object "inherits" the last State name used is easily solved by having a variable of Type int (or you could be using an Enum) called 'LastStateSpecified, or whatever: set it every time the act of adding a new 'Person object is completed, and the State field is set. Then, when you create the next 'Person object: use the value of that variable ...as the Combobox Index ... to set the new ComboBox to the correct State.
best, Bill
"Every two days we create as much information as we did from the dawn of civilization up until 2003". Eric Schmidt of Google.
modified 25-Feb-12 2:40am.
|
|
|
|
|
If we have 2 form (Form1 & Form2) whitin a project
and we added an object (for example textBox1) to
Form1, how can we access to textBox1 from Form2.
i have done this in form2 by these codes
{
Form1 fr = new Form1();
.
.
.
}
but fr doesn't show textBox1 durring writing codes.
i suppose fr.textBox1 must be correct but it is not.
please tell ne how can i do that.
|
|
|
|
|
The simplest but wrongest way would be to make the TextBox public.
A better way is to make a public property that allows the other form to get and/or set the Text property of the TextBox.
There are other ways that may be more appropriate to your situation, but we would need to know more about what you are trying to do.
However you do it, you may have to protect against cross-thread access problems.
|
|
|
|
|
I want to get the properties value of that object and change it to
a new value as I want.
|
|
|
|
|
You would have to change the access modifier for the textbox.
Why is common sense not common?
Never argue with an idiot. They will drag you down to their level where they are an expert.
Sometimes it takes a lot of work to be lazy
Individuality is fine, as long as we do it together - F. Burns
|
|
|
|
|
by changing the modifier I only can get the properties of
that object (the values can be read) how can we set the
properties to a new value?
|
|
|
|
|
Pass value between forms using events[^] explains the correct way to do such things.
What you had, creating yet another Form1, is not going to work, as you are looking at one instance of Form1 and programmatically changing another unrelated instance.
Making Controls public would work but is hardly acceptable, as now "the whole world" could modify, move, resize, etc. said Control.
|
|
|
|
|
|
I hope this will help:
Form1 frm=new Form1();
frm.Show();
TextBox textBox=frm.Controls.Find("textBox1",false)[0] as TextBox;
textBox.Text = "new text";
|
|
|
|
|
I'm working on a custom Attribute. What I'd like is to have it take a parameter (e.g. [MyAttribute(foo)] ), but the type I want to use isn't allowed (non-constant).
So, I made my Attribute abstract and derived other Attributes to specify the desired values:
class FooAttribute : MyAttribute
{
public FooAttribute() : base ( foo ) {}
}
class BarAttribute : MyAttribute
{
public BarAttribute() : base ( bar ) {}
}
This works as expected except that instances of both derived Attributes can then be applied and they don't get flagged as duplicates (of MyAttribute); from a certain point of view, AllowMultiple=false should disallow multiple instances of the base class. In practice this doesn't happen, and that's understandable, but I want to find a way to get it to work that way.
I investigated the TypeId property thinking that would work, but it doesn't seem to.
Has anyone here happened upon this situation and found a solution?
Currently my code is just using the first instance of MyAttribute it finds, but I'm considering having the code throw an Exception if it finds multiples -- does anyone here have an opinion on which course of action is better?
|
|
|
|
|
I am making a program in which I established connection with sql server using DSN. I am using ODBCConnection class. I want to check that, DSN which is created is for access or sql server. I did google but not getting helpful information. I am using c# and visual studio 2008.
Thanks.
|
|
|
|
|
Unless you are developing your program to work with both -- as in using Access for testing, but SQL Server for production, then I don't really see a need to do this.
If you are doing that, then I might suggest that you create a table with that information and query it.
If, on the other hand, you are given a Connection and want to determine which it is, then the best I can say is to use the GetSchema method and examine the resultant table for clues.
|
|
|
|
|
I need to validate dsn name that it is valid or not. Like we can choose any dsn name which is for access, excel, or sql server.
|
|
|
|
|
If you want to check whether or not a given DSN points to your database, then I suggest making a Connection, calling GetSchema, and looking for your tables.
|
|
|
|
|
Hi All,
I have a printed document with lots of check-boxes, I must automatically detect which check-boxes are marked, and save these into a database. (Using C#)
Can anybody give me some hints where to start digging or examples of how I should start on this task.
Thanks alot.
|
|
|
|
|
Certainly willing to try
If the images will be obtained from a scanner, I'd suggest that you first implement code that will detect the skew angle and correct it. I seem to remember adapting some code with a name of gmeDeskew or something like that.
Next, you'll want to define the areas of interest. That is, the areas that will contain check-boxes that should be examined. Since different skew angles will result in images of slightly different sizes when deskewed, I'd suggest that these areas are defined using percentage of document width/height, as opposed to being defined in terms of number of pixels.
Once you have correctly deskewed the image and identified the areas of interest, you'll want to scan the image line-by-line, row by row to determine areas likely to contain check-boxes within your area of interest. Once done, examine the heck-boxes by simply counting the number of percentage of pixels that are below a certain brightness (you'll have to determine this threshold)
I coded an app once that would take scanned images of (college) attendance sheets, identifying the class name/week from a barcode, the student IDs from barcodes, then finally - the student attendance from manually colored 'radio buttons'
With this method, I was able to take an example image (at 1/4 scale as it happened) then deskew it and draw rectangles around each of the 18 barcodes for student ID, the 18 attendance scores for the students, the class name barcode and the class date barcode.
Then when I used full size images all of my areas of interest remained aligned correctly. (Using percentages of image size GREATLY improved the accuracy of the placement of the areas of interest onto each successive image. Prior to that idea, it was very difficult to be sure that I was going to examine the pixels that made up the parts of the image I was interested in)
Something else to consider is "pattern matching", or put simply - the comparing of pre-existing images with portions of the scanned document. You could simply use two images - one of an empty square and another of a check-box with a cross/dot/dash inside it. This should be effective because regardless of the style of marking, an empty box is always going to more closely resemble the saved image you have of an empty box (rather than the checked-box).
It's an interesting topic, OMR. (optical mark recognition) Enjoy!
|
|
|
|
|
The image is scanned from the scanner, and i want to get the marked check-boxes.
Please provide me a sample code if you can .
Thanks
|
|
|
|
|
Here you go - here's the VB code to calculate the skew angle of an image.
I'd throw you the C# version, but I don't have one - I converted this code to c++
You can then find an algorithm to rotate by -skewAngle. (I'll leave that to you)
I might add, I spent many 10s of hours on this project. For your own sanity, I suggest patience!
Imports Microsoft.VisualBasic
Public Class deskew
Public Class HougLine
Public Count As Integer
Public Index As Integer
Public Alpha As Double
Public d As Double
End Class
Dim cBmp As Bitmap
Const stepsPerDeg = 5
Const minAngle = -13
Const maxAngle = 13
Dim cAlphaStart As Double = minAngle
Dim cAlphaStep As Double = 1 / stepsPerDeg
Dim cSteps As Integer = (maxAngle - minAngle) * stepsPerDeg
Dim cSinA() As Double
Dim cCosA() As Double
Dim cDMin As Double
Dim cDStep As Double = 1
Dim cDCount As Integer
Dim cHMatrix() As Integer
Public getPixelCalls As Long
Public Sub setAngleRange(ByVal minAngle As Long, ByVal maxAngle As Long)
cAlphaStart = minAngle
cSteps = (maxAngle - minAngle) / cAlphaStep
End Sub
Public Function GetSkewAngle() As Double
Dim hl() As deskew.HougLine
Dim i As Integer
Dim sum As Double
Dim count As Integer
Calc()
hl = GetTop(20)
For i = 0 To 19
sum += hl(i).Alpha
count += 1
Next
Return sum / count
End Function
Private Function GetTop(ByVal Count As Integer) As HougLine()
Dim hl() As HougLine
Dim i As Integer
Dim j As Integer
Dim tmp As HougLine
Dim AlphaIndex As Integer
Dim dIndex As Integer
ReDim hl(Count)
For i = 0 To Count - 1
hl(i) = New HougLine
Next
For i = 0 To cHMatrix.Length - 1
If cHMatrix(i) > hl(Count - 1).Count Then
hl(Count - 1).Count = cHMatrix(i)
hl(Count - 1).Index = i
j = Count - 1
While j > 0 AndAlso hl(j).Count > hl(j - 1).Count
tmp = hl(j)
hl(j) = hl(j - 1)
hl(j - 1) = tmp
j -= 1
End While
End If
Next
For i = 0 To Count - 1
dIndex = hl(i).Index \ cSteps
AlphaIndex = hl(i).Index - dIndex * cSteps
hl(i).Alpha = GetAlpha(AlphaIndex)
hl(i).d = dIndex + cDMin
Next
Return hl
End Function
Public Sub New(ByVal bmp As Bitmap)
cBmp = bmp
End Sub
Private Sub Calc()
Dim x As Integer
Dim y As Integer
Dim hMin As Integer = cBmp.Height / 4
Dim hMax As Integer = cBmp.Height * 3 / 4
Init()
For y = hMin To hMax
For x = 1 To cBmp.Width - 2
If IsBlack(x, y) Then
If Not IsBlack(x, y + 1) Then
Calc(x, y)
End If
End If
Next
Next
End Sub
Private Sub Calc(ByVal x As Integer, ByVal y As Integer)
Dim alpha As Integer
Dim d As Double
Dim dIndex As Integer
Dim Index As Integer
For alpha = 0 To cSteps - 1
d = y * cCosA(alpha) - x * cSinA(alpha)
dIndex = CalcDIndex(d)
Index = dIndex * cSteps + alpha
Try
cHMatrix(Index) += 1
Catch ex As Exception
Debug.WriteLine(ex.ToString)
End Try
Next
End Sub
Private Function CalcDIndex(ByVal d As Double) As Double
Return Convert.ToInt32(d - cDMin)
End Function
Private Function IsBlack(ByVal x As Integer, ByVal y As Integer) As Boolean
Dim c As Color
Dim luminance As Double
getPixelCalls += 1
c = cBmp.GetPixel(x, y)
luminance = (c.R * 0.299) + (c.G * 0.587) + (c.B * 0.114)
Return luminance < 140
End Function
Private Sub Init()
Dim i As Integer
Dim angle As Double
getPixelCalls = 0
ReDim cSinA(cSteps - 1)
ReDim cCosA(cSteps - 1)
For i = 0 To cSteps - 1
angle = GetAlpha(i) * Math.PI / 180.0#
cSinA(i) = Math.Sin(angle)
cCosA(i) = Math.Cos(angle)
Next
cDMin = -cBmp.Width
cDCount = 2 * (cBmp.Width + cBmp.Height) / cDStep
ReDim cHMatrix(cDCount * cSteps)
End Sub
Public Function GetAlpha(ByVal Index As Integer) As Double
Return cAlphaStart + Index * cAlphaStep
End Function
End Class
|
|
|
|
|
Hello guys!
I am trying to use the following code to send an email to a mail server over a tcp connection. The code works great, however, when I try to send an email to someone, the receipt of my Email alwyes gets unknown sender(From). Am I missing something?
TcpClient SmtpServ = new TcpClient("smtp.my.com", 25);
string Data;
byte[] szData;
string CRLF = "\r\n";
try
{
NetworkStream NetStrm = SmtpServ.GetStream();
StreamReader RdStrm = new StreamReader(SmtpServ.GetStream());
Console.WriteLine(RdStrm.ReadLine());
Data = "HELO server" + CRLF;
szData = System.Text.Encoding.ASCII.GetBytes(Data.ToCharArray());
NetStrm.Write(szData, 0, szData.Length);
Console.WriteLine(RdStrm.ReadLine());
Data = "MAIL From:" + " me@test.com" + CRLF;
szData = System.Text.Encoding.ASCII.GetBytes(Data.ToCharArray());
NetStrm.Write(szData, 0, szData.Length);
Console.WriteLine(RdStrm.ReadLine());
Data = "RCPT TO: " + "me@my.net" + CRLF;
szData = System.Text.Encoding.ASCII.GetBytes(Data.ToCharArray());
NetStrm.Write(szData, 0, szData.Length);
Console.WriteLine(RdStrm.ReadLine());
Data = "DATA" + CRLF;
szData = System.Text.Encoding.ASCII.GetBytes(Data.ToCharArray());
NetStrm.Write(szData, 0, szData.Length);
Console.WriteLine(RdStrm.ReadLine());
Data = "SUBJECT: my subject\r\n\r\n";
Data += "Hello there!\r\n";
Data += ".\r\n";
szData = System.Text.Encoding.ASCII.GetBytes(Data.ToCharArray());
NetStrm.Write(szData, 0, szData.Length);
Console.WriteLine(RdStrm.ReadLine());
Data = "QUIT" + CRLF;
szData = System.Text.Encoding.ASCII.GetBytes(Data.ToCharArray());
NetStrm.Write(szData, 0, szData.Length);
Console.WriteLine(RdStrm.ReadLine());
NetStrm.Close();
RdStrm.Close();
Console.WriteLine("Close connection");
Console.WriteLine("Send mail successly..");
}
catch (InvalidOperationException err)
{
Console.WriteLine("Error: " + err.ToString());
}
Thanks,
|
|
|
|
|
The email address in the MAIL FROM: and RCPT TO: lines should be bounded with < and > characters like this:
"MAIL From:" + " <me@test.com>" + CRLF;
I also notice that you are ignoring all server responses so you cannot be sure your message is being accepted correctly. You may also like to consider using the SmtpClient() [^] class to process your mail.
Unrequited desire is character building. OriginalGriff
I'm sitting here giving you a standing ovation - Len Goodman
|
|
|
|
|
Hello Guys,
We are developing an antispyware program in .net and i want to register my product for listing it into windows security center. I Searched a lot about it and got some idea that it can be done through WMI by \\root\SecurityCenter2 namespace and antispywareproduct class. But all i found was to get the information for antispywareproduct class.
Can any one tell me how to add my product to this table.
any ideas will be a great help.
Regards
abhinav
|
|
|
|
|
Hello all,
I found this link .NET TWAIN image scanner[^] on code project, but When I press acuqire it opens a window from my scanner
when I press cancel on it, the whole application get freezed. How to solve this???
plzz
Thx
|
|
|
|
|