Programatically changing field order in Sharepoint 2007 list - c#

I'm adding in two new fields into an already existing Sharepoint list programmatically through a feature. The fields are being added successfully but I have been unable to adjust the column order.
This task is done simply through the UI by going to List Settings and then Column Ordering, but I have been unable to achieve the task programmatically.
Through some research I've seen that you can use the SPContentType of the form to change the ordering of the FieldLinks (as follows):
SPList list = web.Lists["Example List"];
if (list.ContentTypes.Count > 0) {
SPContentType ct = list.ContentTypes[0];
string[] names = {"Example_x0020_One", "Example_x0020_Two", "Example_x0020_Three"};
ct.FieldLinks.Reorder(names);
ct.Update();
}
In this example, I the list would already have "Example One" and "Example Three" columns, and I would add "Example Two" later and then try to order them.
However this approach did not work for me, so if anyone has input on it, that would be appreciated.
The next item I saw is manually changing the SchemaXml of the list to have the proper order of the fields, but I wanted to see if this was the best method.
Any input would be appreciated, thank you for your help.

I took a look at the source of the Column ordering page (formEdt.aspx), it looks like they use web services, not the object model:
function DoBuildAndSubmit()
{
var numFound, currentSelect, selectValue;
var form = document.forms.aspnetForm;
var numFields = form["numSelects"].value;
var xml = "<Fields>";
numFound = 0;
while(numFound < numFields)
{
for(x = 0; x < numFields; x++)
{
currentSelect = form["FormPosition" + x];
if(currentSelect.selectedIndex == numFound)
{
selectValue = currentSelect.options[numFound].value;
xml = xml + "<Field Name=\"" + selectValue + "\"/>" + "\n";
numFound++;
}
}
}
for(x = numFields ; x < 67; x++)
xml = xml + "<Field Name=\"" + form["FormPosition" + x].value + "\"/>" + "\n";
xml = xml + "</Fields>";
document.frmLayoutSubmit["ReorderedFields"].value=xml;
document.frmLayoutSubmit.action = "http://local/_vti_bin/owssvr.dll?CS=65001";
document.frmLayoutSubmit.submit();
}
Now, it might be possible to do through the object model, but I don't have a good feeling about it when the UI is punting.

Here's a powershell version:
# Moves "FieldToBeMoved" after "Description" field
$list = $web.Lists["Documents"]
$ct = $list.ContentTypes[0] # Or find the desired CT
$newOrder = #()
foreach ($field in $ct.Fields)
{
if ($field.StaticName -ne "FieldToBeMoved")
{
$newOrder += $field.StaticName
}
if ($field.StaticName -eq "Description")
{
$newOrder += "FieldToBeMoved"
}
}
$ct.FieldLinks.Reorder($newOrder)
$ct.Update();

I used the code from your answer, except I programmatically examined the content types and fields for the list I wanted to re-order.
//Step 1 (optional): List out the content types and fields for your list to see what is in the list
SPList list = web.Lists[strListName];
string strRet="";
foreach (SPContentType spct in list.ContentTypes)
{
strRet += "<strong>Content Type: </strong>" + spct.Name + ", <strong>Fields</strong>: <br />";
foreach (SPField field in spct.Fields)
{
if (strFieldInfo != "")
{
strFieldInfo += ", ";
}
strFieldInfo += "\"" + field.StaticName + "\"";
}
strRet += strFieldInfo + "<br />-----<br />";
}
//Output the results
lblOutput.Text = strRet;
Now, you'll have an idea of how many content types your list has and what fields are in the list.
By default, if content type management is not enabled, you'll have one content type that has all the fields.
Sample output from the above code:
Content Type: Event, Fields:
"ContentType", "Title", "Location", "EventDate", "EndDate", "Description", "fAllDayEvent", "fRecurrence", "WorkspaceLink", "EventType", "UID", "RecurrenceID", "EventCanceled", "Duration", "RecurrenceData", "TimeZone", "XMLTZone", "MasterSeriesItemID", "Workspace", "Course", "CourseLocation"
Next Step 2 is to change the order of the content type. You can cut and paste from the output from step 1, re-order it, and add "{" and "};" around it to create the string array for the ordering you want.
if (list.ContentTypes.Count > 0)
{
SPContentType ct = list.ContentTypes[0]; //Specify the content type here, if you have more than one content type in your list.
string[] fieldnames = { "ContentType", "Title", "Course", "CourseLocation", "EventDate", "EndDate", "Description", "fAllDayEvent", "fRecurrence", "WorkspaceLink", "EventType", "UID", "RecurrenceID", "EventCanceled", "Duration", "RecurrenceData", "TimeZone", "XMLTZone", "MasterSeriesItemID", "Workspace", "Location"};
ct.FieldLinks.Reorder(fieldnames);
web.AllowUnsafeUpdates = true;
ct.Update(true);
web.AllowUnsafeUpdates = false;
}

Related

My database query is only querying the last element of my array

My problem in the title i have allcodes array and codes TextBox (kodTxtBox)
i will split textbox like line per element and querying all elements with for loop then
when i run it, it shows the query of only the last element of the allcodes array with the
messagebox, but the others go into else and giving error message box
some turkish words in my codes so.
aciklama = description
birim = monad
birimFiyat = Price per 1 unit
ürünler = products
ürünler.sipariskod = products.ordercode etc.
i did a lot of ways for this i used foreach all variables type is string
allCodes = kodTxtBox.Text.Split('\n');
for (int i = 0; i < allCodes.Length; i++)
{
queryString = "SELECT ürünler.siparisKod, ürünler.aciklama, ürünler.birim, ürünler.fGrup, ürünler.birimfiyat FROM ürünler WHERE (((ürünler.siparisKod)=\"" + allCodes[i] + "\"));";
using (OleDbCommand query = new OleDbCommand(queryString))
{
query.Connection = connection;
reader = query.ExecuteReader();
if (reader.Read())
{
MessageBox.Show(allCodes[i] + " Succesful");
var desc = reader["aciklama"].ToString();
var monad = reader["birim"].ToString();
var sellPrice = reader["birimFiyat"].ToString();
MessageBox.Show("Açıklama: " + desc + " Birim: " + monad + " Satış Fiyatı: " + sellPrice);
reader.Close();
}
else
{
MessageBox.Show("Hata");
}
}
}
I solved the problem by making a single query instead of multiple queries. I saved the values ​​returned in each single query into a list and at the end I made the necessary for loop using the elements of the list

Listview ForeColor per item

This application is a message board type of app. You post a message, which is stored in an Oracle database. The user's photo, name, date and message are displayed in a listview. Everything works however a feature request for font color changing came in. Now testing things below I know I can display ALL of the messages as a certain color.
What I'm going to do is add a 'color' column to my table. Then if a user selects the text of their message to be 'red' for example, I am going to store the hex color for red in the color column of the table for that post.
So what I'm trying to figure out is when that message is retrieved, how I can set this code to 'If color column empty, post message as black, else if hex color exist for each message post that particular message in that color' Without changing the color of every message to red as the code below currently does.
List<MsgBoard> Messages = MsgBoard.find_ActiveByBoardName(Convert.ToString(cmbgroup.SelectedItem));
int i = 0;
imageList1.Images.Clear();
foreach (MsgBoard m in Messages)
{
AddImages(m.EmpPic);
ListViewItem Message = new ListViewItem("", i);
if (m.AlertNo == 0) //Default Message Post (non Alert)
{
Message.UseItemStyleForSubItems = false;
Message.SubItems.Add(m.EmpName.First);
Message.SubItems.Add(m.MessageText + Environment.NewLine).ForeColor = Color.Red;
Message.SubItems.Add(m.PostDate.ToString());
Message.SubItems.Add(m.EmpName.EmpNo.ToString());
Message.SubItems.Add(m.EmpName.Name);
listView1.Items.Add(Message);
}
i++;
}
}
Just to clarify. If 20 people post a message and all 20 select a different color to post their message in. So in the DB all 20 rows have a different color in the DB column, I need to have those messages displayed in listview individually based on the color they posted as. I currently am only aware of applying a single color to all messages in listview as shown in my example above.
Looks like thanks to Stephan, once I add
Message.SubItems.Add(m.MessageText + Environment.NewLine).ForeColor = System.Drawing.ColorTranslator.FromHtml(m.Color);
I then need help adjusting my query to add the color once colors are added to the color column. Here is that code.
Had DB admin add MESSAGE_COLOR varchar column.
I edit this below to existing code, for the newly created column MESSAGE_COLOR when posting..
public string Create()
{
try
{
OleDbDataReader result = Database.Conn.Execute(
"INSERT INTO MPCS.MEYER_BOARD (" +
"EMPLOYEE_ID, " +
"POST_DATE, " +
"BOARD_NAME," +
"ALERT_NO," +
"MESSAGE_TEXT," +
"MESSAGE_COLOR," +
"ACTIVE_FLAG" +
") VALUES (?,SYSDATE,?,?,?,?)",
new List<OleDbParameter> {
new OleDbParameter("EMPLOYEE_ID",EmpName.EmpNo),
new OleDbParameter("BOARD_NAME",BoardName),
new OleDbParameter("ALERT_NO",AlertNo),
new OleDbParameter("MESSAGE_TEXT",MessageText),
new OleDbParameter("MESSAGE_COLOR",MessageColor),
new OleDbParameter("ACTIVE_FLAG",ActiveFlag ? "Y" : "N")
}, Query.ReaderType.Reader);
result.Read();
result.Close();
return null;
}
catch (Exception ex)
{
return ex.Message;
}
}
I then editing DB read w/ the new column as well.
public static MsgBoard DBRead(OleDbDataReader result,string alias=null)
{
return new MsgBoard
{
EmpName = Employee.DBRead(result, "EMPLOYEE"),
MessageText = result[alias + "MESSAGE_TEXT"].ToString(),
MessageColor = result[alias + "MESSAGE_COLOR"].ToString(),
BoardName = result[alias +"BOARD_NAME"].ToString(),
AlertNo = (int)(decimal)result[alias +"ALERT_NO"],
PostDate = (DateTime)result[alias +"POST_DATE"],
ActiveFlag = result[alias +"ACTIVE_FLAG"].ToString().ToString() == "Y",
EmpPic = ImageResource.DBRead(result, "IR")
};
}
But do I need to edit my build_query?
public static String build_query(String where, string OrderBy = null)
{
List<String> cols = new List<String>();
cols.AddRange(db_columns.ConvertAll(c => "MPCS.MEYER_BOARD." + c + " AS MBOARD_" + c));
cols.AddRange(Employee.db_columns.ConvertAll(c => "MPCS.EMPLOYEE." + c + " AS EMPLOYEE_" + c));
cols.AddRange(ImageResource.db_columns.ConvertAll(c => "MPCS.IMAGE_RESOURCE." + c + " AS IR_" + c));
String sql =
"SELECT " + String.Join(", ", cols) + " " +
"FROM MPCS.MEYER_BOARD " +
"LEFT OUTER JOIN MPCS.EMPLOYEE " +
"ON MPCS.MEYER_BOARD.EMPLOYEE_ID=MPCS.EMPLOYEE.EMPLOYEE_ID " +
"LEFT OUTER JOIN MPCS.IMAGE_RESOURCE " +
"ON MPCS.IMAGE_RESOURCE.IR_ID=MPCS.EMPLOYEE.IMAGE_RESOURCE_ID " +
"WHERE ";
sql += where;
sql += OrderBy;
return sql;
}
UPDATE
I've gotten everything coded and I am submitting the color to the DB now. However when displaying the listview below each post still just has a default black text color. Rather than the color saved for example as "#FFF000" being converted and displayed.
foreach (MsgBoard m in Messages)
{
AddImages(m.EmpPic);
ListViewItem Message = new ListViewItem("", i);
if (m.AlertNo == 0) //Default Message Post (non Alert)
{
Message.SubItems.Add(m.EmpName.First);
Message.SubItems.Add(m.MessageText + Environment.NewLine).ForeColor = System.Drawing.ColorTranslator.FromHtml(m.MessageColor);
Message.SubItems.Add(m.PostDate.ToString());
Message.SubItems.Add(m.EmpName.EmpNo.ToString());
Message.SubItems.Add(m.EmpName.Name); //Displayed only on 'Show Details'
listView1.Items.Add(Message);
}
Final update
Turns out the last piece I was missing was to change the listview property UseItemStyleForSubItems = false; now its working.
You can convert your hex value (assuming that it is stored as a string in the format "#RRGGBB") into a color using ColorTranslator
Using this approach, you can also use named colors (like "Violet")
Message.SubItems.Add(m.MessageText + Environment.NewLine).ForeColor =
System.Drawing.ColorTranslator.FromHtml(m.Color); //sth. like "#FFCC66"
Furthermore you have to retrieve the value of the Color column. It seems that you have to add "MESSAGE_COLOR" (or whatever your column is called) to your db_columns. When you got the values from the DB, you have to map the column to the property of your Message:
return new MsgBoard
{
// ...
Color = System.Drawing.ColorTranslator.FromHtml([alias+"MESSAGE_COLOR"]),
// ...
}
(In other words: You already save it to db, now you also have to read it from DB)

Can Anyone help me retrieve data from parse using unity please?

I have managed to store data, but I can't retrieve it and i would be so grateful if someone could just help me get at least 1 example working.
First I am storing data when the user signs up:
public void SetupNewParseMember(ParseUser user)
{
ParseObject gameScore = new ParseObject("GameScore");
gameScore["cash"] = 500;
gameScore["playerName"] = user.Username;
gameScore["HighestCash"] = 500;
gameScore["GamesPlayed"] = 0;
Task saveTask = gameScore.SaveAsync();
}
This works fine, I can see the data in parse and all seems ok..
The problem is when i try to retrieve the objects.
public void SetupMainScreen(ParseUser user)
{
var query = ParseObject.GetQuery("GameScore").WhereEqualTo("playerName", user.Username);
query.FindAsync().ContinueWith(t =>
{
IEnumerable<ParseObject> results = t.Result;
List<ParseObject> resultsList = results.ToList();
DealWithResults(resultsList, user);
});
}
public void DealWithResults(List<ParseObject> resultsList, ParseUser me)
{
userGamesPlayed = resultsList[1].Get<int>("GamesPlayed");
userHighestCash = resultsList[2].Get<int>("HighestCash");
userCash = resultsList[3].Get<int>("Cash");
WelcomeText.text = "Welcome, " + me.Username + "\n" +
"Cash: $" + userCash + "\n" +
"Highest Cash: $" + userHighestCash + "\n" +
"Games Played: " + userGamesPlayed;
}
First I tried just making changes to the unity ui from inside the Query but that did not work, So i made an outside function and passed the results to it that way, and that still does not work?
I tried to debug what i was getting in the list with this:
foreach (var res in resultsList)
{
Debug.Log("Class Name = " + res.ClassName + "| Keys are: " + res.Keys);
}
But all it returned was:
Class Name = GameScore| Keys are: System.Collections.Generic.Dictionary`2+KeyCollection[System.String,System.Object]
Can anyone offer any insights?
EDIT2:
ok so first i found results list and its contents
http://i.imgur.com/IKcBbey.png
Then if i open it, it seems to be null ref?
http://i.imgur.com/VmSpi9c.png
But if i go digging, i found the info i need all the way down here
http://i.imgur.com/1Wwu5uc.png
Now just need to work out how to get it?
As there is only one set of data it is always accessible through resultsList[0]. What you want is:
double cash = (double)resultsList[0]["cash"];
string playerName = (string)resultsList[0]["playerName"];
double highestCash = (double)resultsList[0]["HighestCash"];
int gamesPlayed = (int)resultsList[0]["GamesPlayed"];
Though you probably want to check that resultsList is not null and contains one element before you try to dereference it.
Also as your ParseObject appears to be a Dictionary you might find this MSDN page useful.
Ended up solving it.. Much different to the examples...
I had to make a coroutine that called a function on callback to access the variables outside of the query.
I called it with
StartCoroutine(SetupMainScreen(me, DealWithResults));
then called this.
public IEnumerator SetupMainScreen(ParseUser user, Action<GameScore> callback)
{
var query = ParseObject.GetQuery("GameScore").WhereEqualTo("playerName", user.Username).FirstOrDefaultAsync();
while (!query.IsCompleted)
{
yield return null;
}
if (query.IsFaulted || query.IsCanceled)
{
Debug.Log("Getting of GameScores faulted or cancelled...");
}
else
{
var obj = query.Result;
if (obj != null)
callback(new GameScore(obj.Get<int>("cash"),obj.Get<string>("playerName"),obj.Get<int>("HighestCash"),obj.Get<int>("GamesPlayed")));
}
}
public void DealWithResults(GameScore gs)
{
WelcomeText.text = "Welcome, " + gs.Username + "\n" +
"Cash: $" + gs.Cash + "\n" +
"Highest Cash: $" + gs.HighestCash + "\n" +
"Games Played: " + gs.GamesPlayed;
}
And i just made a class to hold the objects.. Hopefully this helps someone else.

generic export of the contents of a list

I quite often use Lists to store content as a sort of database.
I would create a specific Class that holds a series of propertiesafter which I would export the contents of that list to an external textfile.
For the export I would use something like:
string output = string.empty;
for (int i=0; i<myList.count; i++)
{
output += myList[i].property1 + ";" + myList[i].property2 + ";" + myList[i].property3 + ";" + myList[i].property4 + ";" + myList[i].property5 + Environtment.NewLine;
}
File.WriteAllText(#"c:\mytextfile.txt", output);
This works like a charm, the only issue is that I have to create an export-routine for every list with a specific class in the application.
I would like to make this a bit more generic in the sense that I would like to create a single export-routine, in which I can pass the name of the List which will then automatically detect the number of parameters in the List and next, export all the different values into the textfile which would have the name of the List.
Something like this pseudo-code:
private void (List selectedList)
{
for (int i=0; i<selectedList.count; i++)
{
output += string.join(";",items) + environment.NewLine;
}
File.WriteAllText(filepath + selectedlist + ".txt", output);
}
Does anybody have an idea on how to solve this?
Thank you.
To get a list of properties on an object is going to involve using reflection.
This is a little rough since I'm not in front of VS at the moment, but if you pass it a List<Foo> it will write a file called Foo.txt
private const string rootPath = #"C:\Temp\";
private static void WriteFile<T>(List<T> selectedList)
{
var props = typeof(T).GetProperties();
var sb = new StringBuilder();
foreach (var item in selectedList) {
foreach (var prop in props) {
var val = prop.GetValue(item);
sb.Append(val);
sb.Append(";");
}
}
sb.AppendLine();
var fileName = string.Format("{0}{1}.txt", rootPath, typeof (T).Name);
File.WriteAllText(fileName, sb.ToString());
}
Please be aware using reflection can be quite slow. There is plenty of room for optimisation in the above.

C# dynamic table creation : display table data in aspx page using linq query in a wcf service

I'm a C# newbie_and in programming in general_ and in a previous question C# return linq result as a list from a wcf service method then use it in aspx web forms page , I managed to return a row from a table and display the result in labels in my apx web forms page. Now I want to display the whole table-> an unknown number of rows. I edited my code and I was almost successful. The problem is that the table that I get, instead of the four different rows that my table contains, displays the first one four times. I check again and again but I can't find the error nor some friends. Here is my code:
staffPanel.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
displayClients_Ref.IdisplayClientsSrvcClient dcClient = new displayClients_Ref.IdisplayClientsSrvcClient();
List<string> allClients = new List<string>(dcClient.displayClients());
foreach (string row in allClients)
{
int size = 0;
string client = allClients.FirstOrDefault();
if (String.IsNullOrEmpty(client))
{
// record cannot be found
}
else
{
string[] columns = client.Split(';');
size = columns.Length;
TableRow tr = new TableRow();
allClients_tbl.Rows.Add(tr);
for (int i = 0; i < size; i++)
{
TableCell tc = new TableCell();
tc.Text = columns[i];
tr.Cells.Add(tc);
}
}
}
}
displayClient.svc.cs
public List<string> displayClients()
{
List<string> result = new List<string>();
try
{
using (paragon_db_Models.clients_Entity context = new paragon_db_Models.clients_Entity())
{
var query = from cl in context.clients
select cl;
foreach (var c in query)
{
string row = c.user_account_id + ";" + c.client_name + ";" + c.client_surname + ";" + c.business_name + ";" + c.client_address + ";" + c.postal_code + ";" + c.telephone_number + ";" + c.fax + ";" + c.email + ";" + c.fiscal_code + ";" + c.public_fiscal_service;
result.Add(row);
}
}
return result;
}
catch (Exception)
{
return result;
}
}
If it is a simple, stupid little mistake that I cannot see I will remove the question. I'm open to suggestions and comments concerning a different way of doing this.
You don't need
string client = allClients.FirstOrDefault();
You are already getting the info you want with "row" in
foreach (string row in allClients)
Replace your "client" instances with "row". FirstOrDefault would always get the first object or null.

Categories

Resources