Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Locked thread
Crazy Mike
Sep 16, 2005

Now with 25% more kimchee.
Going through a C# book (Stephens' C# Programming with Visual Studio 2010 24-Hour Trainer) and am having a mysterious problem with one of the exercises. The program has two forms, the main form having text boxes and buttons, click a button and the other form comes up with a List View where you select an item, click OK and the main form's text box has that item in it.

My problem is that the List View form does not have any items highlighted by default or remember what item was highlighted before. The code looks nearly identical to the book code that works and I can't find a difference that would cause this.

My main form code
code:
public partial class Form1 : Form
    {
        

        public Form1()
        {
            InitializeComponent();
        }
        
        //private fields hold the indexes of user choice
        private int SessionIndex1 = 0;
        private int SessionIndex2 = 0;
        private int SessionIndex3 = 0;
        private int SessionIndex4 = 0;

        private void btn1_Click(object sender, EventArgs e)
        {
            PickSessionForm frm = new PickSessionForm();
            frm.Text = "Session " + lbl1.Text;
            frm.SessionIndex = SessionIndex1;

            if (frm.ShowDialog() == DialogResult.OK)
            {
                //Save the new selection
                SessionIndex1 = frm.SessionIndex;
                txt1.Text = frm.SessionTitle;
            }

        }
//three other buttons....
My new form code, looks the same as the book, does not have an initial selection or remember previous selection...
code:
public partial class PickSessionForm : Form
    {
        //public fields to communicate with the main form
        public int SessionIndex;
        public string SessionTitle;
        
        public PickSessionForm()
        {
            InitializeComponent();
        }

        // Initialize the selection
        private void PickSessionForm_Load(object sender, EventArgs e)
        {
            sessionsListView.SelectedIndices.Add(SessionIndex);
            
            // Ensure the selection is visible
            sessionsListView.SelectedItems[0].EnsureVisible();
        }

        //Save the user's selection
        private void btnOK_Click(object sender, EventArgs e)
        {
            SessionIndex = sessionsListView.SelectedIndices[0];
            SessionTitle = sessionsListView.SelectedItems[0].Text;
        }

        
    }
Any ideas what's up with all this?

Adbot
ADBOT LOVES YOU

Crazy Mike
Sep 16, 2005

Now with 25% more kimchee.

Ithaqua posted:

Throw that book in the garbage, it's teaching you horrible practices.

Indeed, I just came off a two week .NET class and seeing some of the things in this book the way it's written out is a bit surprising.

One of the exercises is to "Make a program that displays the days of the week for your next 10 birthdays in a list box." I couldn't think of how to do this without loops which wouldn't be introduced until a later lesson. I came up with
code:
  	private DateTime birthDate;
        private DateTime counter;

        

        private void btnCalculate_Click(object sender, EventArgs e)
        {
            birthDate = DateTime.Parse(txtBirthDate.Text);
            counter = birthDate;
            int i = 0;
            while (counter < DateTime.Now)
            {
                
                counter = birthDate.AddYears(++i);
            }
            
            for (int j = 0; j < 10; j++)
            {
                counter = birthDate.AddYears(i+j);
                listBox.Items.Add(counter.DayOfWeek);
            }
        }
Thinking this looks inelegant I wondered what the solution code was....


code:
 // Display the birthdays.
        private void Form1_Load(object sender, EventArgs e)
        {
            // Make some birthday variables.
            // (This would be much better in an array
            // as described in Lesson 16 or calculated
            // in a loop as described in Lesson 19.)
            DateTime birthday1 = new DateTime(2010, 4, 1);
            DateTime birthday2 = new DateTime(2011, 4, 1);
            DateTime birthday3 = new DateTime(2012, 4, 1);
            DateTime birthday4 = new DateTime(2013, 4, 1);
            DateTime birthday5 = new DateTime(2014, 4, 1);
            DateTime birthday6 = new DateTime(2015, 4, 1);
            DateTime birthday7 = new DateTime(2016, 4, 1);
            DateTime birthday8 = new DateTime(2017, 4, 1);
            DateTime birthday9 = new DateTime(2018, 4, 1);
            DateTime birthday10 = new DateTime(2019, 4, 1);

            birthdaysListBox.Items.Add(string.Format(
                "{0:d} is on a {0:dddd}", birthday1));
            birthdaysListBox.Items.Add(string.Format(
                "{0:d} is on a {0:dddd}", birthday2));
            birthdaysListBox.Items.Add(string.Format(
                "{0:d} is on a {0:dddd}", birthday3));
            birthdaysListBox.Items.Add(string.Format(
                "{0:d} is on a {0:dddd}", birthday4));
            birthdaysListBox.Items.Add(string.Format(
                "{0:d} is on a {0:dddd}", birthday5));
            birthdaysListBox.Items.Add(string.Format(
                "{0:d} is on a {0:dddd}", birthday6));
            birthdaysListBox.Items.Add(string.Format(
                "{0:d} is on a {0:dddd}", birthday7));
            birthdaysListBox.Items.Add(string.Format(
                "{0:d} is on a {0:dddd}", birthday8));
            birthdaysListBox.Items.Add(string.Format(
                "{0:d} is on a {0:dddd}", birthday9));
            birthdaysListBox.Items.Add(string.Format(
                "{0:d} is on a {0:dddd}", birthday10));
        }
This is the first book that I've seen take so long to get to if statements and loops. I just might breeze through the rest of this book and look for something better. Hopefully something that combines .NET with SQL.

Crazy Mike
Sep 16, 2005

Now with 25% more kimchee.
I'm 2 months in to my first programming job and have no idea what I'm doing. My training project last month involved database queries. My coworker gave me a good start by giving me a SQLConnector class that has a method that executes SQL queries from strings.

Using that class I was able to create a SQLFiller class that populates ComboBoxes based on whats in the column, have those Combo Box choices insterted as part of SQL strings for the DataGridViews that display the results of the query. I also added a button that exports the results as a .csv or .txt.


Now I'm trying to understand entity framework as I've been hearing that that's the way things should be done from now on. I've tried reading the book I got from our big training session and didn't understand much past add new ADO.NET Entity Data Model.

I'm trying to build a training project similar to the last one that will do more than display data, but actually take data from a .csv and update the table. Of course right now I just want to be able to push a button and see something and build from there. Considering I'm pretty much learning via plagiarism, where should I look for help with getting better at these programming problems?

Also, how in over my head am I considering I spend most of the day reading programming books and not understanding anything and not understanding the SQL queries I have to write based on vague requirements?

I don't want to give up on this job but I think I got to make a bit more progress soon before it becomes apparent I don't really do anything here.

Crazy Mike
Sep 16, 2005

Now with 25% more kimchee.

Ithaqua posted:

Is there anything specific you're having trouble grasping? Right now, you're just saying "I'm trying to learn this stuff and I can't, help!", which we're not going to be able to do anything about.

Here are my general hints:
- Read Stackoverflow
- Check MSDN
- Google, google, google.

For EF, try this for starters: http://msdn.microsoft.com/en-us/library/bb386876.aspx

If you have any specific questions about how to do something, ask.

Indeed, I needed to vent a bit. I did not have a productive week. I managed to do the schools tutorial last Friday and then make *something* that reached out and touched my dev database, now I just have to learn LINQ better and make it return what I want. That's going on the back burner now because I just got a work order similar to my prior project. In the interest of time I'm falling back to SQL queries passed as strings and combo boxes for variables, this time using date time dialogs to filter out a range of data and providing aggregate information from there. I'm building this from my prior project so it shouldn't be too hard and hope to have something I can show my boss in a couple days. Wish me luck.

Crazy Mike
Sep 16, 2005

Now with 25% more kimchee.

Ithaqua posted:

Please tell me you're using parameterized queries, at least.

E.g. "SELECT * FROM Foo WHERE Bar = @Something" instead of "SELECT * FROM Foo WHERE Bar = '" + someVariable + "'"

Well you learn something new every day.... While the examples I read on the web focused on text field entries, is there a danger in using combo boxes? It seems like a good habit to get into anyways. OK as before when I was using StringBuilder.AppendFormat("SELECT * FROM Foo WHERE Bar = {0}", ComboBox.SelectedItem) I changed it to use
StringBuilder.Append("SELECT * FROM Foo WHERE Bar = @Something");
SQLCommand.Parameters.AddWithValue("@something", ComboBox.SelectedItem);


Is there a similar thing I need to worry about when I get to LINQ queries?

query = from row in query
where row["Something"].ToString() == cmbSomething.SelectedItem.ToString()
select row;

Crazy Mike
Sep 16, 2005

Now with 25% more kimchee.

Ithaqua posted:

The fact that more senior developers let you get that code into a production codebase is a very bad sign.

Is it better than an outsourced Indian at least? Hell if I know...

Crazy Mike
Sep 16, 2005

Now with 25% more kimchee.
Last time I was struggling with stretching SQL strings as far as I could. I have another project that I got till the end of the month to figure out although I would love to get it done sooner.

Before someone would get data in the mail, write it on an excel spreadsheet, send it to me. I would convert that to a .csv and run SQL to import that on the database. The goal is to write a program where he can write the data in there and have it write to the database.

So how do I update the database? I tried a SQL string again and it would not work so I figured now was a good time to try entity framework again.
I went through the Data Source Configuration Wizard to get my Model1.edmx.

I create the object I want to become a new row on the database by matching the properties with the text boxes.
code:

DateTime now = DateTime.Now;

            
TERMINATIONS term = new TERMINATIONS


                {
                    first_name = txtFirstName.Text,
                    mi = txtMI.Text,
                    last_name = txtLastName.Text,
                    order_number = txtOrderNumber.Text,
                    date_received = receivedDateTimePicker.Value,
                    last_processed_datetime = now,
                    created_datetime = now
                };
I watch Julie Lerman do it at 3:30
https://www.youtube.com/watch?v=EMvWojwKIrk

She has
code:
var context = new AWEntities()
////
context.Customers.AddObject(customer);
context.SaveChanges(); 
I have
code:
 DevEntities devEntities = new DevEntities();
////
devEntities.TERMINATIONS.AddObject(term);
devEntities.SaveChanges();
When I hit the button to run this code I get the error "Unable to update the EntitySet 'TERMINATIONS' because it has a DefiningQuery and no <InsertFunction> element exists in the <ModificationFunctionMapping> element to support the current operation."

Why does she use var instead of the Entities class as the object type like the Wrox books demonstrate? I tried var and got the same error. Anyways research on that error suggests the problem may be lack of a primary key in the table. A more senior team member is going to help me with the key issue tomorrow but in the meantime, what other pieces to this puzzle am I missing?


***update*** Solved the problem by following advice at
http://stackoverflow.com/questions/1589166/it-has-a-definingquery-but-no-insertfunction-element-err

Crazy Mike fucked around with this message at 20:50 on Aug 22, 2012

Crazy Mike
Sep 16, 2005

Now with 25% more kimchee.
PROBLEM:
Someone's birthday is in a datagridview cell in yyyy/mm/dd format. I want to get a copy of it in mm/dd/yyyy format in a masked text box in case it's wrong and needs to be edited. After all, I'm pretty sure his birthday isn't 19/81/1028.
SOLUTION:
code:
string convertedDOB = (string)datagridview[7, e.RowIndex].Value;
string convertedYear = convertedDOB.Remove(4);
string convertedMonthDay = convertedDOB.Remove(0, 5);
convertedDOB = (convertedMonthDay + convertedYear);
mtxtDOB.Text = convertedDOB;
This looks like it works. The masked text box inserts the slashes automatically so i don't have to put .Replace("/", string.Empty) at the end of convertedDOB. Is there a more elegant way to solve this problem? Is this a case where I should be using StringBuilder instead?

Crazy Mike
Sep 16, 2005

Now with 25% more kimchee.
Another problem with my queries I'm trying to solve. I am getting different results when I try to get a LINQ version of my SQL string involving a left outer join, multiple join conditions, and including null values... something similar to

code:
SELECT 
tableA.columnA,
tableB.columnA,
tableA.columnB,
tableB.columnB,
tableA.columnC,
tableB.columnC,

FROM tableB
LEFT OUTER JOIN tableA
ON tableB.columnA = tableA.columnA AND tableB.columnB = tableA.columnB
AND tableA.columnC NOT IN ('1', '2', '3', '4', '5')
ORDER BY tableB.columnA
code:
var result = from b in context.tableB
                                  join a in context.tableA
                                  on  new 
                                  {     b.columnA , 
                                        b.columnB 
                                  } 
                                  equals new 
                                  { 
                                      a.columnA ,
                                      columnB = a.columnB
                                  } 
                                  
                                  into b_a  
                                  from a in b_a.DefaultIfEmpty()
                                  
                                  where a.columnC  != "1"
                                  where a.columnC  != "2"
                                  where a.columnC  != "3"
                                  where a.columnC  != "4"
                                  where a.columnC  != "5"

                                  orderby b.columnA
                                  select new
                                  {
                                     	a.columnA,
					b.columnA,
					a.columnB,
					b.columnB,
					a.columnC,
					b.columnC,
                                  };
The main difference I can see is that the LINQ query will not display values where the join condition a.columnB is null. It looks like I am getting an inner join instead of a left join. I tried following along with http://www.codeproject.com/Articles/169590/LINQ-to-SQL-Left-join-with-null-values but could not alter my results. So what's missing here and how do I make the results match the SQL query?

Crazy Mike
Sep 16, 2005

Now with 25% more kimchee.

Okita posted:

You probably already figured this out by now, but why not wrap this SQL up in a database view? You can then import the view into your project .dbml and use it as if it were a LINQ table.

If you're using SQL server, you can also make it an indexed view for better performance.

My solution to writing complex LINQ to SQL: If I can't write the query in less than 3-4 lines of LINQ to SQL statements, then it goes into a database view/stored proc/UDF.

Actually I stuck with the SQL query and put my other attempt in a method that never gets called to be fixed later. I actually don't understand what the recommendation you're making is. (I am probably one of the most junior programmers out there.)

I've spent the past month working on this program and recently got significant suggestions for improvement in a code review. I've been working on most of them and hope the results are more satisfactory at the next review.

I'm starting to wonder if this will get into production this year. It was supposed to be done last month.

Crazy Mike
Sep 16, 2005

Now with 25% more kimchee.

Okita posted:

view advice

Thanks for the tip. I tried it out and got it to display in my DataGridView. I am probably not going to use it in the final product because using a view or the old entity framework display loses the automatic sorting by clicking a column header.

Which leads to another thing I'm trying to figure out... how do I make that triangle in the column header indicating the sort direction disappear?

Crazy Mike
Sep 16, 2005

Now with 25% more kimchee.
I've been looking at a method that validates e-mail addresses today and wondering how much of it needs to be cleaned up.
code:
public static bool ValidEmail(string EmailAddress)
{
	// Validates Email Addresses before sending.
        int AtSignIndex; 
	string AtSign = "@";
            
	int TwoDotsIndex;
        string TwoDots = ".."; 

	AtSignIndex = EmailAddress.IndexOf(AtSign);
	// This checks to see if the @ sign is at least the second character.
	//ie [email]A@Yaho0.com[/email] is OK, but @Yahoo.com is not a legitimate address.
	if (AtSignIndex < 2)
		{
		// Email Addresses Must Have AT LEAST 1 Character Before the @ Sign
			return false;
		}

		// A lot of erroneous address are of the format MyAddress@Yahoo..Com 
		//This catches them easily 
	TwoDotsIndex = EmailAddress.IndexOf(TwoDots);

	if (TwoDotsIndex > AtSignIndex)
		{
		// Cannot have two dots in a row AFTER the @ Sign 
			return false;
		}

	// Regex Expression 
            
	Regex rxInsensitive = new Regex("^[A-Z0-9._%+-]+@[A-Z0-9.-]+.[A-Z]{2,4}$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
	if (rxInsensitive.IsMatch(EmailAddress))
		{
			return true;
		}
	else
		{
			return false;
		}
}
My first thought was... we're sending in the email address as a string, would it make more sense to initialize the index variables as int AtSignIndex=EmailAddress.IndexOf("@") and string TwoDots = EmailAddress.IndexOf("..")?

Second, shouldn't it be if (AtSignIndex < 1) due to zero indexing?

Third, I never used/don't know regex, but shouldn't they be able to check for these two issues? Doesn't it already check that the first character isn't @? After reading http://www.regular-expressions.info/email.html it mentions you can exclude two dot matches by replacing [A-Z0-9.-]+\. with (?:[A-Z0-9-]+\.)+

The website also mentions successive dots aren't allowed before the @ either, although that is something not usually tested for. If we don't worry about that, can we make that change to the regex to allow for not matching two dots and get rid of everything before it?

Crazy Mike
Sep 16, 2005

Now with 25% more kimchee.

ninjeff posted:

Fix up those PascalCase parameter and local variable names while you're at it!

The big long term project we need to do is taking our main application written in Power Builder and rewriting it in .NET. The current naming convention is "<scope><type>_Name", so imagine me removing li_ and ls_ from those local int and string variables just for forums readability. We need to look into changing that as we move into .NET. When that time comes I'm going to build a comparison chart of what we have to what MSDN recommends, but it would help if I could articulate why we shouldn't do things that way and switch to what MSDN recommends.

The small project this method came from was built by a former employee as a learning .NET exercise. My learning .NET exercise is trying to understand how it works/should work, and hopefully actually making it work.

Crazy Mike
Sep 16, 2005

Now with 25% more kimchee.
I had my second code review for my small project that's taking a long time.

The biggest thing I need to improve is learning what happens if multiple users are running the program and try to update the database? Are there appropriate locks and constraints to prevent problems?

Is there a difference in that behavior in the SqlConnection/SqlTransaction objects and the Entity Framework objects in that regard?

We also got into a discussion on how I should think about moving much of that to the database as a stored procedure.

I'm going to spend some time reading about SQL programming so I can hopefully fake an intelligent answer when asked these questions and then decide what I'm going to do about it.

Minor things to improve were adding a control that only programmers can see to choose the database instead of commenting/uncommenting code as necessary, changing the blink property on the error providers, and figuring out how to use one entity framework model for multiple databases by changing the connection string.

Crazy Mike
Sep 16, 2005

Now with 25% more kimchee.
I'm working on a program that reads a text file and determines if each line meets certain criteria. I got something that works, but am wondering if some assumptions I made are not good practices. The main one I'm concerned with is if the file is a text file?
code:
//is it a text file?
  if (openFileDialog.FileName.Remove(0, openFileDialog.FileName.Length - 4) == ".txt")
   {
	//big foreach loop with 14 validation checks
   }
I remember MSDN mentioned not to expect certain behavior based on file name. Is this a problem that needs to be fixed or nothing to worry about?

I'm also not too happy that I couldn't figure out how to use a Background Worker to update the text boxes while a large file was being processed and used Application.DoEvents(); in the loop instead.

I've got about one day left for minor improvements and it works now, so I'm wondering if I should worry about these types of things or turn each validation check into a separate method so the foreach loop isn't so big. Since seven of those checks involved is this position in the string the delimiter character?, I spent today making that its own method along with making sure each validation does what its supposed to.

Crazy Mike
Sep 16, 2005

Now with 25% more kimchee.
My screw up at work today...

I wrote a program that sends a couple SQL queries on a timer. The first query calculates a number, the second query updates a table row with a message about what the number is and when it was calculated. I use a Timer that ticks every second to show a clock on the form, and decides whether to run the query based off DateTimePicker and ComboBox values. When I switched to the production server, the times did not match. I was using DateTime.Now to determine when to run the queries and select GETDATE()to determine when the calculation was performed. The two clocks were off by a minute. My boss would prefer basing time off the server instead of DateTime.Now.

So lets think of possible solutions...
1.) I know the clock is off by a minute so I will offset the program to run a minute later to compensate. This really doesn't solve anything though...

2.) I can just change the SQL string for the second query to have the time variable from the local machine instead of the server. This goes against the preference that we use the server time instead of the local machine time.

3.) My timer will query select GETDATE() at every tick to ensure that the time is synchronized. This results in a lot of unnecessary queries run, something I'm pretty sure we should avoid.

4.) We run the program off the server instead of the local machine so that DateTime.Now and select GETDATE() are the same. Is this the right answer or is there a better way to solve this problem?

Crazy Mike
Sep 16, 2005

Now with 25% more kimchee.
I've got another problem I'm trying to solve. I'm working on a form. In the form's load event is a call to the database setting the ownership of that form to the user. In the form's closed event is a call to the database setting the ownership to an empty string.

If the ownership of the form is not an empty string during the load event it means someone else owns it. A MessageBox asks if you want to override the setting and force the window open. If you click yes it updates the ownership, if you click no it closes the form.

The problem is the ownership of the form shouldn't be reset to an empty string when you click no on the MessageBox. Object sender and FormClosedEventArgs e are the same for both calls, so how do I differentiate between them to make the right choice in the event?

Crazy Mike
Sep 16, 2005

Now with 25% more kimchee.

gariig posted:

This sounds like a logic problem to me. Are you saying in the Form.Load you are checking to see if someone "holds" this piece of data like an Order. If there is someone else viewing this Order the second person can either Force an Open or just stop viewing the order? When you say I don't want to view the order in the Form.Load event you are calling Form.Close() which your Form.FormClosed event doesn't know why the Form is being close. Is that the problem? Does it matter why the Form is closing and your ownership variable is blank? If it matters you'll have to keep some sort of state in your Form or a ViewModel of the Form state to pass around.

Indeed I had to very slowly write this out on a whiteboard to figure out what I should do. I added a bool variable to determine if when the form is closing it should reset it.

If the load event successfully updates ownership, bool iOwnIt = true, when the closed event is called I wrapped the giveUpOwnership method in an if (iOwnIt){}
If you hit no on the MessageBox in the load event, the variable hasn't been set yet so the closed event doesn't go inside the if statement.

Crazy Mike
Sep 16, 2005

Now with 25% more kimchee.
Success... after putting my rather frustrating project on hold for a few months, I finally figure out how to use app.config to have my entity framework model connect to different databases. It only took a three hour WebEx with a senior programmer to unscrew half the project.

While I'm glad he was able to fix the problems in the designer constructor, we ended the meeting on a cliffhanger where he didn't think we could use app.config to change the configuration file at runtime and wanted either to comment/uncomment a connection string in the config file or change the connection string in the class (which genereated exceptions due to readonly problems), or have a separate model for each database.

I'm thinking that doesn't seem right, so after the meeting I added the string in app.config and after some minor fixes, got it working.

Now I got a WebEx tomorrow to show him how it works.

Crazy Mike
Sep 16, 2005

Now with 25% more kimchee.

aBagorn posted:

Would you mind explaining?

What would you like explained? Once I learned we access the connection string for entity framework through ConfigurationManager.ConnectionStrings["name"].ToString() and the connection string for SQL commands through ConfigurationManager.AppSettings["key"] I created variables for the key and name that were changed with a ComboBox. It was not knowing how to access the different connection strings that was getting me stuck.

Crazy Mike
Sep 16, 2005

Now with 25% more kimchee.
Some stuff I've been going over the past couple of days...
Problem 1: I gave a program I made to a technician which to my surprise did not work. SqlException The SELECT permission was denied on the object. It worked on my machine because programmers have more database permissions than technicians.

Solution1: I looked at a program my coworker wrote to see how he solved it. The difference is in the app.config file that stores the connection strings. Instead of using Integrated Security=true he had the SQL Server User ID and Password in the string.

Problem 2: I was concerned that having our SQL Server information in an easily accessible plain text format was not a good idea.

Solution 2: I added a SQL call in the code to a table that every user has access to that verifies the user is in a list then takes the value received from app.config and replaces Integrated Security = true to the SQL login in the program.

Problem 3: That leaves the people who can get our password to those who can read the MSIL files, and the boss wants to minimize stuff like passwords and SQL hard coded in the application.

Result: He recommended going back to solution 1 and not worrying about the password being in plain text at this time. For the future, what is the preferred way of handling this security vulnerability? I've tried looking up encryption for app.config on Stack Overflow and YouTube which resulted in different and relatively complicated results.

Crazy Mike
Sep 16, 2005

Now with 25% more kimchee.
Here's my headache for today. I have a DataGridView where I want certain columns centered, but changing the Alignment property seems to have no effect. After the DataGridView is populated I can alter the alignment of the column headers, but not the subsequent rows.
code:
DataGridViewCellStyle centered = new DataGridViewCellStyle();
centered.Alignment = DataGridViewContentAlignment.MiddleCenter;
centered.ForeColor = Color.Red;
            
DataGridViewCellStyle columnHeaders = new DataGridViewCellStyle();
columnHeaders.WrapMode = DataGridViewTriState.True;
columnHeaders.BackColor = Color.LightGray;
columnHeaders.Alignment = DataGridViewContentAlignment.MiddleCenter;

dgr.ColumnHeadersDefaultCellStyle = columnHeaders; //Column Headers are centered 
//Format Columns

DataGridViewColumn columnToCenter = dgr.Columns[0];
columnToCenter.Width = 50;
columnToCenter.DefaultCellStyle = centered; //Subsequent rows in this column are red but not centered 
Stack overflow suggested that the style may be overridden but I don't see where that could be happening in this program besides in the form design. Is there anything else that I may not be thinking of?

edit: I needed a fresh mind to figure this out...
code:
for (int i = 0; i < dgr.RowCount; i++)
            {
                
                dgr.Rows[i].Cells[0].Style.Alignment = DataGridViewContentAlignment.MiddleCenter;
                dgr.Rows[i].Cells[1].Style.Alignment = DataGridViewContentAlignment.MiddleCenter;
                dgr.Rows[i].Cells[2].Style.Alignment = DataGridViewContentAlignment.MiddleCenter;
                dgr.Rows[i].Cells[12].Style.Alignment = DataGridViewContentAlignment.MiddleCenter;
            }

Crazy Mike fucked around with this message at 17:47 on Jul 1, 2013

Crazy Mike
Sep 16, 2005

Now with 25% more kimchee.
A coworker asked me why I write so many static classes/methods. I said that I don't want to have to create a new object every time I want to use that method. In this case the class and methods are for running SQL queries to populate DataGridViews or update tables. She is concerned that static methods are more likely to result in memory leaks or have a bigger footprint. Is that a valid concern? Should I rewrite this class so it isn't static?

Crazy Mike
Sep 16, 2005

Now with 25% more kimchee.

Ithaqua posted:

Just a heads up: If you're looking to get a Microsoft cert, 70-483 (Programming in C#) is ridiculously easy. I took it today on a whim (and because my employer set one of my 2013 goals to be "get a cert"), and I scored 975/1000.

I'll probably buy the Wrox book first, but this will definitely be on my radar.

Crazy Mike
Sep 16, 2005

Now with 25% more kimchee.
Today's problem: I am trying to filter a DataGridView based on a column containing a TextBox value. The DataGridView's DataSource is set to a DataView so I can use its RowFilter() method. The TextBox Text changed event contains two methods. One that sets the filter, and another the reformats the DataGridView Columns since the filter resets the columns to defaults. If I type in the TextBox too fast, then the FormatColumns() method runs a for loop on a count of rows larger than it should, resulting in a Data Error and empty cells/rows in the DataGridView beyond what the filter returns. If I comment out the FormatColumns() method, there is no Data Error, but I lose my column formats. How do I ensure the FormatColumns() method has the right count of rows to operate on? The pertinent code is similar to the following:

code:
 private void TextBox_TextChanged(object sender, EventArgs e)
        {
            //Since the text changed, we need a new filter...
            SetFilter();
            // Since the filter resets the column widths, we need to reset them, This one is causing problems
            FormatColumns();        
        }
 private void SetFilter()
        {
            DataView.RowFilter = string.Format("title like '%{0}%'", TextBox.Text);
        }
 private void FormatColumns()
        {
            DataGridViewCellStyle columnHeaders = new DataGridViewCellStyle();
            columnHeaders.WrapMode = DataGridViewTriState.True;
            columnHeaders.BackColor = Color.LightGray;
            columnHeaders.Alignment = DataGridViewContentAlignment.MiddleCenter;

            // Need to center certain columns in the data grid
            for (int i = 0; i < DataGridView.RowCount; i++)
            {
                DataGridView.Rows[i].Cells[0].Style.Alignment = DataGridViewContentAlignment.MiddleCenter;
                DataGridView.Rows[i].Cells[1].Style.Alignment = DataGridViewContentAlignment.MiddleCenter;
                DataGridView.Rows[i].Cells[2].Style.Alignment = DataGridViewContentAlignment.MiddleCenter;
                DataGridView.Rows[i].Cells[12].Style.Alignment = DataGridViewContentAlignment.MiddleCenter;
            }

            DataGridView.ColumnHeadersDefaultCellStyle = columnHeaders;
	}
edit: And it looks like I can use a cell template instead of a for loop to center those columns...
code:
 	 private void FormatColumns()
        {
            DataGridViewCellStyle columnHeaders = new DataGridViewCellStyle();
            columnHeaders.WrapMode = DataGridViewTriState.True;
            columnHeaders.BackColor = Color.LightGray;
            columnHeaders.Alignment = DataGridViewContentAlignment.MiddleCenter;
	    // Format column headers
	    DataGridView.ColumnHeadersDefaultCellStyle = columnHeaders;
            
	    // Certain columns need to be centered, therefore we need a cell template that corresponds
            DataGridViewCell cellTemplate = new DataGridViewTextBoxCell();
            cellTemplate.Style.Alignment = DataGridViewContentAlignment.MiddleCenter;

            //Format Column widths, give columns 0, 1, 2, and 12 the centered template

            DataGridViewColumn column= DataGridView.Columns[0];
            column.Width = 50;
            column.CellTemplate = cellTemplate;
	    //snip..
	}
            
Since the defaults aren't affected by setting the filter, I only have to call this method once after the data grid is populated.

Crazy Mike fucked around with this message at 19:42 on Jul 30, 2013

Crazy Mike
Sep 16, 2005

Now with 25% more kimchee.
Remember a few months ago when I noticed that our app.config has our database connection string user name/password in plain text and that could be a problem? Well we're finally getting around to fixing that. One suggestion given here was to use integrated security and handle the user permissions for the application. That's a pain in the rear end that no one in here wants to be saddled with. I've been told we can't have a webservice handle the connection because we don't have the right hardware or something. Now that leaves us with the option of encrypting the app.config.

When we use the ClickOnce deployment, there are multiple config files put on the user's machine, so we have to go up a directory and hunt them all down to encrypt them. Luckily someone else solved this problem which we borrowed liberally from. In the Program.cs file we call EncryptAllConfigs() right before Application.Run(new form());

code:
 static void EncryptAllConfigs()
        {
            // Is this a ClickOnce Application?
            if (ApplicationDeployment.IsNetworkDeployed)
            {
                //Is this the first time this version is run?
                if (ApplicationDeployment.CurrentDeployment.IsFirstRun)
                {
                    // Get paths
                    Assembly asm = Assembly.GetExecutingAssembly();
                    // This is the name of the application
                    string exeName = System.IO.Path.GetFileName(asm.Location);
                    // The config file has .config appended to the name
                    string configName = exeName + ".config";
                    // Since multiple config files are put in directories descended from the parent directory 
                    // but not limited to the directory of the executing assembly, 
                    // we get the parent directory for a starting point of our search
                    DirectoryInfo parentPath = Directory.GetParent(Directory.GetCurrentDirectory());

                    try 
                    {
                        // Protect config files
                        foreach (DirectoryInfo dir in parentPath.GetDirectories())
                        {
                            foreach (FileInfo fil in dir.GetFiles())
                            {
                                // Is the file the config file we're looking for?
                                if (fil.Name == configName)
                                {
                                    ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
                                    fileMap.ExeConfigFilename = fil.FullName;
                                    Configuration config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
                                    // Set the 2nd argument to the tag in the config file you want to encrypt
                                    ProtectSection(config, "connectionStrings");
                                    config.Save(ConfigurationSaveMode.Modified);
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show("exception" + ex.Message.ToString());
                    }
                }
            }

 private static void ProtectSection(Configuration config, string sectionName)
        {
            // Get the section
            ConfigurationSection section = config.GetSection(sectionName);
            // Throw exception if null
            if (section == null)
            {
                throw new Exception(string.Format("Section '{0}' not found in '{1}'.", sectionName, config.FilePath));
            }
            // If section is not already encrypted, encrypt it
            if (!section.SectionInformation.IsProtected)
            {
                section.SectionInformation.ProtectSection("DataProtectionConfigurationProvider");
            }
            // The associated configuration section will be saved even if it is not modified
            section.SectionInformation.ForceSave = true;
        }
This leads to the last issue we are trying to solve, there is still an unencrypted config file in the deployment folder on our share drive, so we are going to see if we can block the ability to enter the folder but still allow the application to set up each new version of the program. From what I read at http://technet.microsoft.com/en-us/library/bb727008.aspx It doesn't look like there's an easy way to do this. Stack Overflow has a similar question that led to a complicated looking MSDN. Is there a simple way to solve this problem?

Crazy Mike
Sep 16, 2005

Now with 25% more kimchee.

Dietrich posted:

Just hard code it.

I've tried to convince my boss that this was getting circular and we should just hard code it. He still wants to see this encrypt app.config/hiding the folder thing instead.

Crazy Mike
Sep 16, 2005

Now with 25% more kimchee.
How do I get started with Unit Testing?
I have been asked to update one of my programs and figured this might be a good time to practice this much hyped skill. Some things I have to do:
  • Add a scroll bar to a text box.
  • Add a new new text box to the form.
  • Make sure the text box changes visiblity/position based on a checkbox
  • Add a column to the associated table for that Text Box
  • Create a row in a code table for the new column in the database
  • Update CRUD buttons/ stored procedures/DataGridView for new text box
  • Increase another column /textbox max length from varchar(20) to varcahr(30)

How many of these tasks are candidates for testing? Starting with adding a scroll bar I run into the problem that the TextBox is private and various websites saying either we don't need to test private objects or make them all internal and change the assembly info. For practice I made it internal just to see if I could write a test, which led to a NullReferenceException.
code:
        [TestMethod]
        public void ScrollBarsVerticalTest()
        {
            // Arrange
            Form myForm = new Form();
            TextBox tb = new TextBox();
            // Act
            tb.ScrollBars = myForm.myTextBox.ScrollBars;
            // Assert
            Assert.AreEqual(tb.ScrollBars, ScrollBars.Vertical);
        }
Are there some baby steps into unit testing I can work into here?

Crazy Mike
Sep 16, 2005

Now with 25% more kimchee.
I'm still working on my WPF Bulk Email program. One of the changes I made was switching the email body from a text box to a rich text box. Email content is saved in the database in rtf format. After choosing an email, I use an rtf to html converter I found somethere to have the mail sent in html format. The next improvement is to have images sent in the email. When the images are saved in the rtf file, they do not get sent with the html conversion. Online examples show the email being built in html and the images stored locally instead of the email/image coming from a rich text box. Where should I start looking for progress on this issue? Is using a rich text box to create and store emails and then converting to html the wrong approach for this type of problem?

Crazy Mike
Sep 16, 2005

Now with 25% more kimchee.
My problem for today: How do I get the source of a Model Validation error?
We start off with:
code:
@Html.ValidationSummary()
And want to build something that scrolls to the input that's not validating.
I can build something like in this stack overflow question.

code:
<table>
         @{foreach (ModelState modelState in ViewData.ModelState.Values)
           {
               foreach (ModelError error in modelState.Errors)
               {
                <tr><td>Fix This!</td><td>@error.ErrorMessage</td></tr>
               }

           }}
</table>
But need to figure out how to get the id so that the cell would be like
code:
<td onclick="scrollTo('@ID???')">
We have something like this in javascript, but instead of adapting that I'm hoping there's some simpler way available.

Adbot
ADBOT LOVES YOU

Crazy Mike
Sep 16, 2005

Now with 25% more kimchee.
I'm starting to take a deeper look at http://www.codeproject.com for introductory projects on various topics in the attempt to expand my knowledge base. Are there any other sites like that you can recommend, preferably with better written explanations?

  • Locked thread