Saturday, April 5, 2008

Enable read only column as editable when it is a new row

Yesterday I saw a post at bytes.com .NET forum a question that sounded like this

"I am using datagrid to display records from access db. I got the first field as ID which is primary key. As users should not edit it i made that column as read only but i need that column to be editable when users tries to add a new record(row). I am using windows forms (vb.net)"

Now I tried to solve this problem and this is what I've got:


// Step 1
DataGridTableStyle tableStyle = new DataGridTableStyle();
tableStyle.MappingName = "Products";
DataColumnCollection myDataColumns = ds.Tables["Products"].Columns;
// Step 2
DataGridTextBoxColumn dgTbCol;
foreach (DataColumn dataColumn in myDataColumns)
{
dgTbCol = new DataGridTextBoxColumn();
dgTbCol.MappingName = dataColumn.ColumnName;
dgTbCol.ReadOnly = true;
tableStyle.GridColumnStyles.Add(dgTbCol);
}
dataGrid1.TableStyles.Add(tableStyle);
// Step 3
ds.Tables["Products"].TableNewRow += new DataTableNewRowEventHandler(Form1_TableNewRow);
ds.Tables["Products"].RowChanged += new DataRowChangeEventHandler(Form1_RowChanged);
dataGrid1.CurrentCellChanged +=new EventHandler(dataGrid1_CurrentCellChanged);
private void Form1_TableNewRow(Object sender, DataTableNewRowEventArgs e)
{
currentRow = (sender as DataTable).Rows.Count;
GridColumnStylesCollection gcsc = dataGrid1.TableStyles["Products"].GridColumnStyles;
DataRowCollection drc;
foreach (DataGridTextBoxColumn dgTbCol in gcsc)
{
if (dataGrid1.CurrentCell.RowNumber == currentRow)
{
Console.WriteLine(dataGrid1.CurrentCell.RowNumber) ;
dgTbCol.ReadOnly = false;
}
}
}
private void Form1_RowChanged(Object sender, DataRowChangeEventArgs e)
{
GridColumnStylesCollection gcsc = dataGrid1.TableStyles["Products"].GridColumnStyles;
foreach (DataGridTextBoxColumn dgTbCol in gcsc)
{
dgTbCol.ReadOnly = true;
}
}
private void dataGrid1_CurrentCellChanged(Object sender, EventArgs e)
{
GridColumnStylesCollection gcsc = dataGrid1.TableStyles["Products"].GridColumnStyles;
foreach (DataGridTextBoxColumn dgTbCol in gcsc)
{
// currentRow should be a global variable
if (dataGrid1.CurrentCell.RowNumber != currentRow)
{
Console.WriteLine(dataGrid1.CurrentCell.RowNumber) ;
dgTbCol.ReadOnly = true;
}
}
}

Now I'm sure this isn't the best way to do and I have One REMARK: i've made all columns readonly and then is added a new row all are editable in new row. U can make minor changes to accomodate it to ur requirements.
U should pay attention to events TableNewRow, RowChanged, and CurrentCellChanged, if u have questions ask.

Friday, April 4, 2008

Load user configurations from xml file stored in MySQL

So now I'm gonna show you how I loaded XML saved previously in MySQL. I took the row with the user ID and putted it as
a parameter in my new
LoadUserConfig function. Then I began to study XmlDocument class and found out
that it has wonderful functions .Load(File fileName) which loads XML from a file (which of course wasn't what I really wanted) & another functions .LoadXml(string strSomething) which loads XML directly from string. After that I just used a simple XPath expression to find the nodes that I really wanted and then just use the data from nodes. That's all!

private void LoadUserConfigs(UsersDataSet.T_UsersRow dr)
{
SetFilterCountryCmb(Agences);

XmlDocument xd = new XmlDocument();
xd.LoadXml(dr.MEM_CONFIG);

string xpathExpression = "//fields/field";

XmlNodeList nodes = xd.SelectNodes(xpathExpression);

if (nodes.Count > 0)
{
foreach (XmlNode node in nodes)
{
((ToolStripMenuItem)this.fieldsToolStripMenuItem.DropDown.Items[int.Parse(node.InnerText)]).Checked = false;
//grid.Column(int.Parse(node.InnerText)).Visible = false;

}
}

xpathExpression = "//filters/idCountry";
XmlNode nodeIdCountry = xd.SelectSingleNode(xpathExpression);

xpathExpression = "//filters/idAgency";
XmlNode nodeIdAgency = xd.SelectSingleNode(xpathExpression);

cmbFilterCountry.SelectedValue = int.Parse(nodeIdCountry.InnerText);
cmbFilterAgency.SelectedValue = int.Parse(nodeIdAgency.InnerText);

xpathExpression = "//sorted/key";
XmlNode nodeKey = xd.SelectSingleNode(xpathExpression);
sortedLast = nodeKey.InnerText;


xpathExpression = "//sorted/value";
XmlNode nodeValue = xd.SelectSingleNode(xpathExpression);
sortedCritere = nodeValue.InnerText;

//Console.WriteLine("KEY: " + nodeKey.InnerText + " VALUE: " + nodeValue.InnerText);

if (nodeKey.InnerText != string.Empty || nodeValue.InnerText != string.Empty)
{
SortDataTable(Users, nodeKey.InnerText, nodeValue.InnerText);
}


xpathExpression = "//date/year";
XmlNode nodeYear = xd.SelectSingleNode(xpathExpression);

xpathExpression = "//date/month";
XmlNode nodeMonth = xd.SelectSingleNode(xpathExpression);

CurrentDate = new DateTime(int.Parse(nodeYear.InnerText), int.Parse(nodeMonth.InnerText), 1);


}

Thursday, April 3, 2008

Entering XML in MySQL Database

Few days I was working on a task: I needed to remember user configurations, put them into an XML and save it all in a MySQL column.

1. Make an XML (How to) from users configurations


private string GetXml(bool addId, string id)
{

StringWriter stringWriter = new StringWriter();
XmlTextWriter xmltextWriter = new XmlTextWriter(stringWriter);
xmltextWriter.Formatting =
Formatting.Indented;

// Start document
xmltextWriter.WriteStartDocument();

xmltextWriter.WriteStartElement(
"userConfigs");
if (addId) xmltextWriter.WriteAttributeString("id", id.ToString());

xmltextWriter.WriteStartElement(
"fields");


///
/// Here we're gonna see what Columns were present in the grid
///

xmltextWriter.WriteAttributeString(
"unchecked", "true");

ToolStripDropDownMenu parent = fieldsToolStripMenuItem.DropDown as ToolStripDropDownMenu;

for (int counter = 0; counter <>if (!((ToolStripMenuItem)parent.Items[counter]).Checked)
{
xmltextWriter.WriteElementString(
"field", counter.ToString());
}
}

xmltextWriter.WriteFullEndElement();

///
/// Now let's see how it was sorted
///
xmltextWriter.WriteStartElement(
"sorted");
xmltextWriter.WriteElementString(
"key", sortedLast);
xmltextWriter.WriteElementString(
"value", sortedCritere);
xmltextWriter.WriteFullEndElement();


///
/// Now let's see how it was filtered
///
xmltextWriter.WriteStartElement(
"filters");
xmltextWriter.WriteElementString(
"idCountry", cmbFilterCountry.SelectedValue.ToString());
xmltextWriter.WriteElementString(
"idAgency", cmbFilterAgency.SelectedValue.ToString());
xmltextWriter.WriteFullEndElement();

///
/// Month and date
///
xmltextWriter.WriteStartElement(
"date");
xmltextWriter.WriteElementString(
"year", dateLast.Year.ToString());
xmltextWriter.WriteElementString(
"month", dateLast.Month.ToString());
xmltextWriter.WriteFullEndElement();


// End document
xmltextWriter.WriteFullEndElement();

xmltextWriter.Flush();
xmltextWriter.Close();
stringWriter.Flush();

return stringWriter.ToString();
}


Let's analyse the code: We have a StringWriter which is assigned to stream and we are embedding a XmlTextWriter with it.

XmlTextWriter functions:


XmlTextWriter xmltextWriter = new XmlTextWriter(stringWriter);
xmltextWriter.WriteStartDocument(); // starts the xml document

// starts the new element with specified name .WriteStartElement(string elementName);
xmltextWriter.WriteStartElement("userConfigs");

// adds an attribute .WriteAttributeString(string attributeName, string attributeValue)
xmltextWriter.WriteAttributeString("id", id.ToString());

// starts the new element with InnerText .WriteElementString(string elementName, string innerText)
xmltextWriter.WriteElementString("field", counter.ToString());

//writes the end tag
xmltextWriter.WriteFullEndElement();

//doesn't write the end tag
xmltextWriter.WriteEndElement();

Tuesday, April 1, 2008

Dynamic Web Reference problem.

Hello guys!

I've encountered a problem 2 days ago and till now I don't know how to handle it.
Well the problem is that I have 2 app.configs (one in a class library DAL, another one in Windows Forms UI), so in DAL I've added a Web Reference and changed it's property "URL Behaviour" to Dynamic. So in DAL app.config automatic were added following lines
[code]

[/code]
And automatic was generated a Reference.cs class which made a constructor and overloaded WS methods.

Now when I copy this setting section into UI app.config then it's supposed to be dynamic, this means that I can change the URL setting in UI app.config, and our proxy class (Reference.cs) will also be rebuild for inputted URL.
But it doesn't make this. When I change in UI app.config URL value it changes the ws.Url property to that value but the responce is null.

public WSAgencesAccessor()
{
ws = new P5_PLA.DAL.WsPLA.WsPLA();
// when we put here breakpoint we'll see what ws.Url is equal to value inputted in UI app.config
}
#endregion

#region Get
public AgencesDataSet.T_AgencesDataTable GetAgences()
{
string responce = ws.WsPLAGetAllAgences001(DataUtils.SessionId, Properties.Settings.Default.SRC, DataUtils.SessionIp);
// here responce is equal to null
AgencesDataSet ds = new AgencesDataSet();
new DataUtils().ManageXMLResponceGet(responce, ds);
// after execution of ManageXMLResponceGet I receive a ArgumentNullException
// because of the responce argument
return ds.T_Agences;
}

After examining WS url I know that it works perfectly (tested them in WSDL from Eclipse). Now the Reference.cs looks like this
///
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.1433")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Web.Services.WebServiceBindingAttribute(Name="WsPLAHttpBinding", Namespace="http://localhost:8080/WsPLA/services/WsPLA")]
public partial class WsPLA : System.Web.Services.Protocols.SoapHttpClientProtocol {

private System.Threading.SendOrPostCallback WsPLAGetUsers001OperationCompleted;

private System.Threading.SendOrPostCallback WsPLAGetAllProjets001OperationCompleted;

private System.Threading.SendOrPostCallback WsPLAAjoutPlanif001OperationCompleted;

private System.Threading.SendOrPostCallback WsPLADeletePlanif001OperationCompleted;

private System.Threading.SendOrPostCallback WsPLAAjoutProjet001OperationCompleted;

private System.Threading.SendOrPostCallback WsPLAGetProjetById001OperationCompleted;

private System.Threading.SendOrPostCallback WsPLAGetPlanifs001OperationCompleted;

private System.Threading.SendOrPostCallback WsPLAGetAllAgences001OperationCompleted;

private System.Threading.SendOrPostCallback WsPLAGetAgenceById001OperationCompleted;

private bool useDefaultCredentialsSetExplicitly;

///
public WsPLA() {
this.Url = global::P5_PLA.DAL.Properties.Settings.Default.P5_PLA_DAL_WsPLA_WsPLA;
if ((this.IsLocalFileSystemWebService(this.Url) == true)) {
this.UseDefaultCredentials = true;
this.useDefaultCredentialsSetExplicitly = false;
}
else {
this.useDefaultCredentialsSetExplicitly = true;
}
}

public new string Url {
get {
return base.Url;
}
set {
if ((((this.IsLocalFileSystemWebService(base.Url) == true)
&& (this.useDefaultCredentialsSetExplicitly == false))
&& (this.IsLocalFileSystemWebService(value) == false))) {
base.UseDefaultCredentials = false;
}
base.Url = value;
}
}

public new bool UseDefaultCredentials {
get {
return base.UseDefaultCredentials;
}
set {
base.UseDefaultCredentials = value;
this.useDefaultCredentialsSetExplicitly = true;
}
}

///
public event WsPLAGetUsers001CompletedEventHandler WsPLAGetUsers001Completed;

///
public event WsPLAGetAllProjets001CompletedEventHandler WsPLAGetAllProjets001Completed;

///
public event WsPLAAjoutPlanif001CompletedEventHandler WsPLAAjoutPlanif001Completed;

///
public event WsPLADeletePlanif001CompletedEventHandler WsPLADeletePlanif001Completed;

///
public event WsPLAAjoutProjet001CompletedEventHandler WsPLAAjoutProjet001Completed;

///
public event WsPLAGetProjetById001CompletedEventHandler WsPLAGetProjetById001Completed;

///
public event WsPLAGetPlanifs001CompletedEventHandler WsPLAGetPlanifs001Completed;

///
public event WsPLAGetAllAgences001CompletedEventHandler WsPLAGetAllAgences001Completed;

///
public event WsPLAGetAgenceById001CompletedEventHandler WsPLAGetAgenceById001Completed;

///
[System.Web.Services.Protocols.SoapDocumentMethodAttribute("", RequestNamespace="http://localhost:8080/WsPLA/services/WsPLA", ResponseNamespace="http://localhost:8080/WsPLA/services/WsPLA", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
[return: System.Xml.Serialization.XmlElementAttribute("out", IsNullable=true)]
public string WsPLAGetUsers001([System.Xml.Serialization.XmlElementAttribute(IsNullable=true)] string in0, [System.Xml.Serialization.XmlElementAttribute(IsNullable=true)] string in1, [System.Xml.Serialization.XmlElementAttribute(IsNullable=true)] string in2, [System.Xml.Serialization.XmlElementAttribute(IsNullable=true)] string in3) {
object[] results = this.Invoke("WsPLAGetUsers001", new object[] {
in0,
in1,
in2,
in3});
return ((string)(results[0]));
}

When I change the values of RequestNamespace, ResponceNamespace and Namespace to URL i need everything works fine. So the URL from UI app.config and from Reference.cs should be the same to work. Now how can I change this all thing to a really dynamic behaviour, just changing URL in app.config UI?