Dynamic Checkbox from a txt file entry on a WinForm UI - c#

Good Morning;
Actually have 2 questions. My first is what is this called? A Program? A Module?
WhatIsThisCalled()
{
//workToBeDone
}
I'm trying to create dynamic checkbox(s) from each entry in a text file. I'm trying to reuse the code so I have tried to create the module in a logic file. I feel like I've done this correctly, but I can't test it. I can not figure out how to reference
this.Controls.Add(chk[I]);
to the winForm I want to call it on. The error I get is about it being illegal in a static method. I'm only trying to clear the error (last one) so I can see if it will actually put the checkboxes onto the correct winForm Permissions.cs. Here is my Logic.cs module.
public static void getPermText()
{
Stream fileStream = File.Open(dataFolder + PermFile, FileMode.Open);
StreamReader reader = new StreamReader(fileStream);
string line = null;
do
{
line = reader.ReadLine();
if (line == null)
{
break;
}
string[] parts = line.Split('\n');
try
{
int userCount;
userCount = parts.Length;
CheckBox[] chk = new CheckBox[userCount];
int height = 1;
int padding = 10;
for (int i = 0; i <= userCount; i++)
{
chk[i] = new CheckBox();
chk[i].Name = parts.ToString();
chk[i].Text = parts.ToString();
chk[i].TabIndex = i;
chk[i].AutoCheck = true;
chk[i].Bounds = new Rectangle(15, 30 + padding + height, 150, 22);
this.Controls.Add(chk[i]);
height += 22;
}
}
catch
{
}
} while (true);
}
There is one global int userCount = 0; above that module. On Permissions.cs I have this code (with no errors).
public Permissions()
{
InitializeComponent();
}
private void Permissions_Load(object sender, EventArgs e)
{
WidgetLogic.getPermText();
}
Can anyone please direct me as to how, or if it is possible, to replace Permissions with this in a dynamic format?? I think??
Thank you very much in advance for all that look or help. I really appreciate it. Have a Great Day!! :)

I tired very hard to understand what you wanted to say. I think you just want to reference the form where the CheckBoxes should create.
So you should better pass the reference the of the form on which you want to create the controls:
public static void getPermText(System.Windows.Forms.Form targetForm)
{
//code
targetForm.Controls.Add(chk[i]); //changed "this" to "targetForm"
To call the method:
WidgetLogic.getPermText(this); //here "this" refers to the current form
Now where ever you will call this method it will create the controls on your form (the one you're passing as the parameter).
Notify me if I got your question wrong.

Related

How Do I Apply Validation To Form

I have a requirement where I need to do Find and Replace in datagridview for multiple pages - it's working fine. The problem is, after I find a specific word and replace it and again if I click on Find and Replace button, the earlier find and replace values are gone.
How to work on it?
The code is provided below:
public string toFind = "";
public string toReplace = "";
private void btnFindandReplace_Click(object sender, EventArgs e)
{
Form2 f = new Form2();
f.cmbColumnCombo.DataSource = cmbList;
f.ShowDialog();
toFind = f.txtfind.Text;
toReplace = f.txtreplace.Text;
for (int i = 0; i <= dataGridView1.Rows.Count - 1; i++)
{
if (dataGridView1.Rows[i].Cells[f.cmbColumnCombo.Text].Value.ToString().ToLower().Contains(f.txtfind.Text.ToLower()))
{
if (!string.IsNullOrEmpty(f.txtfind.Text))
{
dataGridView1.Rows[i].Cells[f.cmbColumnCombo.Text].Value =
dataGridView1.Rows[i].Cells[f.cmbColumnCombo.Text].Value.ToString().Replace(f.txtfind.Text, f.txtreplace.Text);
}
}
}
}
Try to initialize your toFind and toReplace variables within the btnFindandReplace_Click method.
Declare your Form object outside of the button click event handler. This will make your form global and operate on the same object.

Data reset after leaving a constructor

I have probably a very beginner question,yet I can't figure out why is it like that. I am trying to pass in constructor a StringBuilder which via Debugger I nailed but as soon as my last step in Debugger leaves this constructor which is in different class, it gets back to null. I know that it is a reference type and therefore only a reference gets copied but even if I pass it by reference by "ref" result is the same...maybe I get it wrong or there is something else wrong...
class DifferentClass
{
public void Method()
{
StringBuilder[] PathtoFiles = new StringBuilder[numberOfImages];
for (int i = 0; i < numberOfImages; i++)
{
PathtoFiles[i] = new StringBuilder();
// string pattern for correct file naming/saving
string nameOfFile = string.Format("{0}{1}{2}", adresaPath, i, ".jpg");
PathtoFiles[i].Append(nameOfFile);
}
Pictures picture = new Pictures(ref PathtoFiles);
}
}
class Pictures
{
public StringBuilder[] sb;
public Pictures(ref StringBuilder[] sb)
{
this.sb = sb;
}
public Pictures()
{
}
public void LoadPictures(ImageList img)
{
for (int i = 0; i < sb.Count(); i++)
{
img.Images.Add(string.Format("pic{0}", i), Image.FromFile(sb[i].ToString()));
}
}
}
Upon request I am enclosing another bit of code this time in class where the method LoadPictures gets called:
class ThirdClass
{
DifferentClass diff = new DifferentClass();
Pictures picture = new Pictures();
private void btn_Download_Click(object sender, EventArgs e)
{
diff.Method();
//this is a control data is supposed to be saved in
picture.LoadPictures(imageList1);
}
}
Well there ya go:
class ThirdClass
{
DifferentClass diff = new DifferentClass();
Pictures picture = new Pictures();
private void btn_Download_Click(object sender, EventArgs e)
{
diff.Method();
//this is a control data is supposed to be saved in
picture.LoadPictures(imageList1);
}
}
You are using the default constructor. Which doesn't set StringBuilder[] Pictures.sb
This is assuming of course that code you re-edited is the code you are working with.
In that case you need to figure out how to instantiate DifferentClass, maybe in ThirdClass ctor. And perhaps you want DifferentClass.Method() to return a Picture object you can initialize also in ThirdClass constructor.
There are several ways you can do this. Up to you to choose the best method.
public void Method()
{
// the StringBuilder
// ...
Pictures picture = new Pictures(ref PathtoFiles);
}
initialization of picture is correct. but it is a local variable, and when Method() is completed, you can't access it anymore
you can modify your method to keep result in variable on client-side:
public Pictures Method()
{
// the StringBuilder
// ...
return new Pictures(ref PathtoFiles);
}
client-side
var pics = new DifferentClass().Method();
ImageList imgs = new ImageList();
pics.LoadPictures(imgs);

How to Clone a Windows Forms Controls even with non-Serializable properties?

How to Clone or Serialize a Windows Forms Control?
When I am trying to Clone windows forms controls using this code "CloneControl(Control ct1)", it allows me to duplicate controls with some Serializable properties, not with all properties.
public Form1()
{
InitializeComponent();
Columns = new DataGridViewTextBoxColumn[2];
for (int i = 0; i < 2; i++)
{
Columns[i] = new System.Windows.Forms.DataGridViewTextBoxColumn();
//
// Columns[i]
//
Columns[i].HeaderText = "j" + (i + 1);
Columns[i].Name = "Column" + (i + 1);
Columns[i].Width = 50;
}
dataGridView1 = new System.Windows.Forms.DataGridView();
dataGridView1.Name = "dataGridView1";
dataGridView1.Location = new System.Drawing.Point(100, 100);
dataGridView1.RowHeadersWidth = 50;
dataGridView1.RowTemplate.Height = 25;
dataGridView1.Size = new System.Drawing.Size(55 + 50 * 2, 25 + dataGridView1.RowTemplate.Height * 2);
dataGridView1.Anchor = System.Windows.Forms.AnchorStyles.None;
dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
dataGridView1.Columns.AddRange(Columns);
dataGridView1.TabIndex = 3;
dataGridView1.AllowUserToAddRows = false;
dataGridView1.Rows.Add();
dataGridView1.Rows.Add();
dataGridView1.Rows[0].HeaderCell.Value = "i" + 1;
dataGridView1.Rows[1].HeaderCell.Value = "i" + 2;
dataGridView1.Rows[0].Cells[0].Value = "value1";
Controls.Add(dataGridView1);
Control cloned1 = CloneControl(dataGridView1);
cloned1.SetBounds(cloned1.Location.X, cloned1.Location.Y + 300, cloned1.Width, ct1.Height);
Controls.Add(cloned1);
cloned1.Show();
}
public Control CloneControl(Control ct1)
{
Hashtable PropertyList = new Hashtable();
PropertyDescriptorCollection Properties = TypeDescriptor.GetProperties(ct1);
Assembly controlAsm = Assembly.LoadWithPartialName(ct1.GetType().Namespace);
Type controlType = controlAsm.GetType(ct1.GetType().Namespace + "." + ct1.GetType().Name);
Control cloned1 = (Control)Activator.CreateInstance(controlType);
foreach (PropertyDescriptor pr1 in Properties)
{
if (pr1.PropertyType.IsSerializable)
{
PropertyList.Add(pr1.Name, pr1.GetValue(ct1));
}
if (PropertyList.Contains(pr1.Name))
{
try
{
Object obj = PropertyList[pr1.Name];
pr1.SetValue(cloned1, obj);
}
catch (Exception ex)
{
}
}
}
return ct2;
}
If you run the code... the you will get
As you can see in the main method I create a clone of dataGridView1, which has a few properties.
And actually each cell value is null in a cloned dataGridView.
Also size of a columns are not cloned!
You may have a question: if Visual Studio or SharpDeveloper as IDE which is written in C# can handle this problem, then it might be possible to write that kind of code! Right?
In Visual Studio When you are trying drag and drop controls, or copy and paste controls, it not only duplicates that controls with all properties (including Serializable or non-Serializable) but also it changes the name of control itself from "dataGridView1" to "dataGridView2" as well as in SharpDeveloper!
What should I do?
What kind of method should I create?
Maybe another control has a many non-Serializable properties!
How to duplicate all of them?
Please anyone.....
Like #Hans mentioned in the comment, Clone is not that easy. If you want to get some identical controls with only a bit different, you'd better use a function to define general behavior and pass the different properties in as parameters. For example, we define a function with some general properties which apply to DataGridView:
private void InitDataGridView(DataGridView dataGridView, string name)
{
dataGridView.Name = name;
// configure other properties here
dataGridView.Location = new System.Drawing.Point(100, 100);
dataGridView.RowHeadersWidth = 50;
dataGridView.RowTemplate.Height = 25;
dataGridView.Size = new System.Drawing.Size(55 + 50 * 2, 25 + dataGridView1.RowTemplate.Height * 2);
dataGridView.Anchor = System.Windows.Forms.AnchorStyles.None;
dataGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
// remember to initialize your columns, or pass it in as a parameter
dataGridView.Columns.AddRange(Columns);
dataGridView.AllowUserToAddRows = false;
dataGridView.Rows.Add();
dataGridView.Rows.Add();
dataGridView.Rows[0].HeaderCell.Value = "i" + 1;
dataGridView.Rows[1].HeaderCell.Value = "i" + 2;
dataGridView.Rows[0].Cells[0].Value = "value1";
}
public Form1()
{
InitializeComponent();
var dataGridView1 = new DataGridView();
var dataGridView2 = new DataGridView();
InitDataGridView(dataGridView1, "dataGridView1");
InitDataGridView(dataGridView2, "dataGridView2");
}
IDE (e.g. Visual Studio) is using PropertyDescriptors, DesignerSerializationVisibility and ShouldSerializeValue, but DataGrid Rows are something special, because you cannot add them at design time! IDE cannot copy something that is not there, so, the solution must be different (if you want to clone controls beyond what IDE/Designer can do - see other answers and comments for this). Try my code (everything except grid rows got cloned without the extra check - the columns got cloned).
foreach(PropertyDescriptor pd in TypeDescriptor.GetProperties(src)) {
if(!pd.ShouldSerializeValue(src)) {
if(src is DataGridView && pd.Name == "Rows")
CopyDataGridRows((DataGridView)src, (DataGridView)dst);
continue; }
Note: The above can be done better (by check for the class at the end), but is as it is to be obvious.
using System;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
namespace CloneControls {
public partial class Form1: Form {
public Form1() { InitializeComponent(); }
private void Form1_Load(object sender, EventArgs e) {
dataGridView1.Rows.Add();
dataGridView1.Rows.Add();
foreach(Control c in splitContainer1.Panel1.Controls)
splitContainer1.Panel2.Controls.Add((Control)Clone(c));
}
static object Clone(object o) {
return Copy(o, Activator.CreateInstance(o.GetType()));
}
static object Copy(object src, object dst) {
IList list = src as IList;
if(list != null) {
IList to = dst as IList;
foreach(var x in list)
to.Add(Clone(x));
return dst; }
foreach(PropertyDescriptor pd in TypeDescriptor.GetProperties(src)) {
if(!pd.ShouldSerializeValue(src)) {
if(src is DataGridView && pd.Name == "Rows")
CopyDataGridRows((DataGridView)src, (DataGridView)dst);
continue; }
switch(pd.SerializationVisibility) {
default: continue;
case DesignerSerializationVisibility.Visible:
if(pd.IsReadOnly) continue;
pd.SetValue(dst, pd.GetValue(src));
continue;
case DesignerSerializationVisibility.Content:
Copy(pd.GetValue(src), pd.GetValue(dst));
continue;
}
}
return dst;
}
static void CopyDataGridRows(DataGridView src, DataGridView dst) {
foreach(DataGridViewRow row in src.Rows)
if(!row.IsNewRow) dst.Rows.Add((DataGridViewRow)Clone(row));
}
}
}
I think I made more better method here.
This Method at first checks interface of property: if it is ICollection then it does the first job.
After this one loop ends in the method "DeepClone()", then it is necessary to do another loop without checking PropertyType Interface... I mean I could not mix these two operation into one loop?!
Also You can detect that there will be some kind of Run-time Exceptions and for this reason I put this code into try-catch block...
Control cloned1 = (Control)DeepClone(dataGridView1);
cloned1.SetBounds(cloned1.Location.X, cloned1.Location.Y + 300, cloned1.Width, ct1.Height);
Controls.Add(cloned1);
cloned1.Show();
public dynamic DeepClone(dynamic ob1)
{
dynamic ob2 = null;
if (ob1.GetType().IsSerializable && !ob1.GetType().IsArray)
{
if (ob1 != null)
{
using (MemoryStream ms = new MemoryStream())
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(ms, ob1);
ms.Position = 0;
ob2 = formatter.Deserialize(ms);
}
}
}
else
{
if (ob1.GetType().IsArray)
{
var r1 = ob1.Rank;
object[] d1 = new object[r1];
long[] V1 = new long[r1];
for (int i = 0; i < r1; i++)
{
V1[i] = 0;
d1[i] = ob1.GetUpperBound(i) + 1;
}
ob2 = Activator.CreateInstance(ob1.GetType(), d1);
for (long i = 0; i <= ob2.Length; i++)
{
ob2.SetValue(DeepClone(ob1.GetValue(V1)), V1);
for (int j = 0; j <= V1.GetUpperBound(0); j++)
{
if (V1[j] < ob2.GetUpperBound(j))
{
V1[j]++;
break;
}
else
{
V1[j] = 0;
}
}
}
}
else
{
PropertyInfo[] P1 = ob1.GetType().GetProperties();
ob2 = Activator.CreateInstance(ob1.GetType());
foreach (PropertyInfo p1 in P1)
{
try
{
if (p1.PropertyType.GetInterface("System.Collections.ICollection", true) != null)
{
dynamic V2 = p1.GetValue(ob1) as IEnumerable;
MethodInfo gm1 = p1.PropertyType.GetMethods().Where(m => m.Name == "Add").Where(p => p.GetParameters().Count() == 1).First(f => V2[0].GetType().IsSubclassOf(f.GetParameters()[0].ParameterType) || f.GetParameters()[0].ParameterType == V2[0].GetType());
if (V2[0].GetType().IsSubclassOf(gm1.GetParameters()[0].ParameterType) || gm1.GetParameters()[0].ParameterType == V2[0].GetType())
{
for (int i = 0; i < V2.Count; i++)
{
dynamic V3 = DeepClone(V2[i]);
gm1.Invoke(p1.GetValue(ob2), new[] {V3});
}
}
}
}
catch (Exception ex)
{
}
}
foreach (PropertyInfo p1 in P1)
{
try
{
if (p1.PropertyType.IsSerializable && p1.CanWrite)
{
var v2 = p1.GetValue(ob1);
p1.SetValue(ob2, v2);
}
if (!p1.PropertyType.IsSerializable && p1.CanWrite)
{
dynamic V2 = p1.GetValue(ob1);
if (p1.PropertyType.GetMethod("Clone") != null)
{
dynamic v1 = V2.Clone();
p1.SetValue(ob2, v1);
}
}
}
catch (Exception ex)
{
}
}
}
}
return ob2;
}
You may say that this Method does not copy some kind of property, But it does copy of main properties and the Cloned control will look like an original control!
Trying to clone a control is overkill except if you really need a totally generic control clone method. Most of the time, you only need to clone a specific control and you have an easy access to the code that created it (see the Form designer generated code, and the setup code you wrote yourself).
But nevertheless, I once used a trick to duplicate many controls at once in order to fill the new tabs of a TabControl, choosing one out of ten tab designs.
I also wanted to use the Form design tool of the C# IDE to edit and modify the 10 template.
So, besides my Tab control form, and using the VS IDE, I created 10 "control factory dummy forms" in my project. I put a dummy Panel control in each of it.
Each time I had to dynamically create a new Tab, I simply instantiated a new dummy window of the desired style. Then I simply moved the Parent pane to my ControlTab (using the Controls.Add() method of the new tab).
This way, you must link the event handlers after the Tab creation (after the controls move). And the event handler's code should be written in you main window class, otherwise you will have "this" reference problems.
Obviously, you will have to store control references somewhere, to be able to access them. The easiest way to do this is to just keep track of each "dummy template Form" you instantiate and to set the "modifier" of your controls to be "public". You can use the Tag property of the destination tab page to store that reference. But, to avoid many casts, it is better to declare an array of each form class, and to store the references there.

Implement block comment/uncomment in ScintillaNET control

I'm trying to implement a custom text-editor in C# using the ScintillaNET component. I've got most of it right until now, but stuck at one point. I want to give the user the ability to block comment/uncomment the selected text. I tried a lot, but cannot find any examples online. The only thing I seem to get from the control's Selection object are the Start and End positions, but that isn't much help
private void commentBlockToolStripMenuItem_Click(object sender, EventArgs e)
{
if (txtSQL.Selection.Text.Length > 0)
{
String start = txtSQL.Selection.Start.ToString();
String end = txtSQL.Selection.End.ToString();
MessageBox.Show(start + "::" + end);
}
}
Were any of you able to successfully implement this using the ScintillaNET control?
EDIT:
After some improvization, I'm able to do it somehow, but after block is commented, last line moves out of selection!
private void commentBlockToolStripMenuItem_Click(object sender, EventArgs e)
{
if (txtSQL.Selection.Text.Length > 0)
{
Range range = txtSQL.Selection.Range;
int f = range.StartingLine.Number;
int t = range.EndingLine.Number;
int endpos = txtSQL.Selection.End;
for (int i = f; i <= t; i++)
{
//txtSQL.GoTo.Line(i);
string tstr = txtSQL.Lines[i].Text.Replace(Environment.NewLine, "");
txtSQL.Lines[i].Text = "--" + tstr;
}
}
}
After a bit of experimentation, I found a way to accomplish this. Though I doubt if it is the most elegant of solutions!
private void commentBlockToolStripMenuItem_Click(object sender, EventArgs e)
{
if (txtSQL.Selection.Text.Length > 0)
{
Range range = txtSQL.Selection.Range;
int f = range.StartingLine.Number;
int t = range.EndingLine.Number;
for (int i = f; i <= t; i++)
{
txtSQL.InsertText(txtSQL.Lines[i].StartPosition,"--");
}
txtSQL.Selection.Start = txtSQL.Lines[f].StartPosition;
txtSQL.Selection.End = txtSQL.Lines[t].EndPosition;
}
}
Actually I found a very simple solution to this. To block comment do
scintilla1.Lexing.LineComment();
And to block uncomment do
scintilla1.Lexing.LineUncomment();

List information disappearing

THIS IS HOMEWORK: I have a program that consists of two winforms and three classes. The program does the work it is supposed to do for the main form and displays it appropriately onto the textbox of the main form. In addition to displaying the information, it is also saved to a string list. The data consists of order information.
The string list passes that information along to a method in another class and stores it in a list as it is supposed to do. After this is done, I press a button which opens up another form. In this form I enter an order number. What is supposed to happen is that a method compares the order number entered with the row number of the list and return that information, whereupon it is displayed in the textbox of the second form.
That is what is supposed to happen. Instead, when it is time to compare the order number with the row number of the list, the list data is gone and I cannot figure out why. Here is my code that pertains:
private void btnPaymentButton_Click(object sender, EventArgs e)
{
amountPaid = double.Parse(this.txtAmountPaid.Text);
orderObject.GetChangeDue(orderObject.TotalAmountDue, amountPaid);
this.txtNumberOfPizzaOrdered.Clear();
this.txtNumberOfCokesOrdered.Clear();
this.txtAmountDue.Clear();
this.txtAmountPaid.Clear();
this.lblYourOrder.Visible = true;
this.rtxtYourOrder.Visible = true;
this.rtxtYourOrder.Text = orderObject.OrderSummary(amountPaid);
//storeOrderObject = new DailySummary(orderObject.OrderSummary(amountPaid));
storeOrderObject = new DailySummary(this.rtxtYourOrder.Text);
}
private void btnDailySummary_Click(object sender, EventArgs e)
{
DailySummaryForm form = new DailySummaryForm();
// this.Visible = false;
form.Show();
}
........
public class DailySummary
{
//declare variables
int numberOfCokes = 0,
numberOfPizzas = 0,
totalOfCokes = 0,
totalOfPizzas = 0,
orderNumberRequest = 0;
string orderFromForm1 = "",
getAllTheOrders = "",
getAnOrder = "";
List<string> pizzaOrderList = new List<string>();
public DailySummary(string orderForm)
{
orderFromForm1 = orderForm;
StoreOrder(orderFromForm1);
}
public DailySummary(int orderRequest)
{
orderNumberRequest = orderRequest;
GetOrder(OrderNumberRequest);
}
public int OrderNumberRequest
{
get
{
return this.orderNumberRequest;
}
}
//store order
public void StoreOrder(string orderFromForm1)
{
pizzaOrderList.Add(orderFromForm1);
}
//get the order
public string GetOrder(int OrderNumberRequest)
{
for (int row = 0; row < pizzaOrderList.Count; row++)
{
if (row == (OrderNumberRequest - 1))
{
getAnOrder = pizzaOrderList[row];
}
}
return getAnOrder;
}
........
public partial class DailySummaryForm : Form
{
int orderNumberRequest = 0;
//instantiate a from object
OrderForm formObject;
DailySummary summaryObject;
public DailySummaryForm()
{
InitializeComponent();
}
private void btnOrderNumberButton_Click(object sender, EventArgs e)
{
orderNumberRequest = int.Parse(this.txtOrderNumber.Text);
summaryObject = new DailySummary(orderNumberRequest);
this.rtxtDisplayOutput.Visible = true;
this.rtxtDisplayOutput.Text = summaryObject.GetAnOrder;
}
In your method btnPaymentButton_Click you create an instance of the DailySummary class, then later on when your in the DailySummaryForm you create a new instance of the DailySummary Class.
These instances are separate and therefore do not share the same values.
As your not persisting values to the DB you'll probably want to:
look into making your DailySummary Static (which will make it accessable throughout your
winform application). (It's not typically good practice to have too many global (static) variables hanging around, but without a persistence engine where you can store your Daily Summary you need a common place to look it up.
Pass the initialized instance of the DailySummary class to your DailySummaryForm. (The DailySummaryForm could expose a public property. The drawback of this method is if your switching between both forms and each form modified your summary class, your going to constantly have to pass it back and forth between the forms.
DailySummaryForm is creating a new instance of
DailySummary.
and that is why it is empty.

Categories

Resources