DateTimeControl in Sharepoint (c#) - c#

I'm trying to change the default values in the "time" drop down list that the DateTimeControl displays in Sharepoint. I want an increment of 15, not 5 minutes. Anybody has any idea how this could be done? Can I overload a method or something?

As a matter of fact both the time drop down and its initializers are implemented as private data members of the DateTimeControl class so you can not change the values directly. However, the minutes drop down is prepared inside OnPreRender, we can get the control and reset its values indirectly to get desired behavior. Here is one approach
public class MyDateTimeControl : DateTimeControl
{
protected override void Render(HtmlTextWriter output)
{
DropDownList minuteControl = null;
string[] newMinutesRange = new string[] { "00", "15", "30", "45" };
string[] newMinutesRangeExt = new string[] { "00", "15", "30", "45", "" };
int index = 0;
int selectedMinutes;
try
{
if (!this.DateOnly && this.Controls.Count == 4)
{
minuteControl = (DropDownList)this.Controls[2];
}
}
catch { }
if (minuteControl != null && !this.DateOnly)
{
selectedMinutes = Convert.ToInt32(minuteControl.SelectedValue);
if (selectedMinutes % 15 > 0)
{
index = 4;
newMinutesRangeExt.SetValue(selectedMinutes.ToString(), index);
newMinutesRange = newMinutesRangeExt;
}
else
{
index = selectedMinutes / 15;
}
minuteControl.Items.Clear();
minuteControl.SelectedIndex = 0;
minuteControl.DataSource = newMinutesRange;
minuteControl.DataBind();
minuteControl.SelectedIndex = index;
}
base.Render(output);
}
}
Hope this helps

Go to
[12]\TEMPLATE\LAYOUTS\1033\BFORM.JS
In line : 7690
Change:
this.dminControl=5;
to
this.dminControl=15;
It works, but all DateTimePickers will have an increment to 15 minutes

Unfortunately this is not possible using the out of the box DateTime field.
A SharePoint field is made up of 2 main parts. The data structure (in code) and the various views (namely in a list, new/edit/view, admin [when adding to a list]). The data structure out of the box is a standard .NET DateTime field. Unfortunately the views only give the increment by 5 minutes.
You can create your own by inheriting from the default field. MSDN has a decent explaination of how. Nick Sevens has a much clearer explanation.
Unfortunately (as with most SharePoint customizations) creating your own field in CAML can be tricky.
This project on CodePlex might be a good starting point. It's licensed under the GPL so you can modify it.

You can get the value of selected Hour and Minute from the SharePoint:DateTimeControl in C# by the following code:
DateTimeControlName.SelectedDate.Hour
&
DateTimeControlName.SelectedDate.Minute.
These statements will return the hour and minute in Integer format.
I know this post is quite old. But I just thought this may help someone coming to this post.

Related

dataGridView column referencing and nested if statements with CellContentDoubleClick event c#

Hi so i see a lot of posts re: cell referencing in a DGV and nested if statements. The post have got me soo far i am very nearly there or maybe not... i am hoping for some help and open to suggestions.
very simply i need to be able to double click on a certain cells in dgv, on double clicking the cell, if that cell is in certain column it applies a 1 or 0 to its relating column.
So, doubling clicking a cell in column 2 applies a figure one or zero depending to the same row but column 5.
so,column 2 relates to 5
6 relates to 9
10 relates to 13
14 relates to 17
18 relates to 21
22 relates to 25
here is what i have so far..i have messed about alot and have taken it so far however i cannot get it to work independently. so, if i double click all columns change not the relating column. at present this doesn’t work. any help would be welcomed.
private void dataGridViewAcorn_CellContentDoubleClick(object sender, DataGridViewCellEventArgs e)
{
commandBuilder = new SqlCommandBuilder(dataAdapter);
dataAdapter.UpdateCommand = commandBuilder.GetUpdateCommand();//get the update command
string HW_A = dataGridViewAcorn.CurrentRow.Cells[5].Value.ToString();
string Crwn_A = dataGridViewAcorn.CurrentRow.Cells[9].Value.ToString();
string HB_A = dataGridViewAcorn.CurrentRow.Cells[13].Value.ToString();
string OV_A = dataGridViewAcorn.CurrentRow.Cells[17].Value.ToString();
string Acorn_A = dataGridViewAcorn.CurrentRow.Cells[21].Value.ToString();
string Brn_A = dataGridViewAcorn.CurrentRow.Cells[25].Value.ToString();
int columnIndex = dataGridViewAcorn.CurrentCell.ColumnIndex;
if (columnIndex == 2)
{
if (HW_A == ("1"))
{
dataGridViewAcorn.CurrentRow.Cells[5].Value = 0;
}
else HW_A = ("0");
{
dataGridViewAcorn.CurrentRow.Cells[5].Value = 1;
}
}
/*
System.Text.StringBuilder messageBoxCS = new System.Text.StringBuilder();
messageBoxCS.AppendFormat("{0} = {1}", "ColumnIndex", e.ColumnIndex);
messageBoxCS.AppendLine();
messageBoxCS.AppendFormat("{0} = {1}", "RowIndex", e.RowIndex);
messageBoxCS.AppendLine();
MessageBox.Show(messageBoxCS.ToString(), "CellConentDoubleClick Event");
*/
dataGridViewAcorn.DataSource = bindingSourceAcorn;
bindingSourceAcorn.EndEdit();// updates table in memory
dataAdapter.Update(table);//actually the data base
//MessageBox.Show("Update Successful!");
}
First of all, create the column dependency object, so you can avoid the multiple ifs. (I know, that it is not optional memory allocation, if you want to optimize, you can use a Dictionary<int, int> object, but I feel like you don't want to mix that into this problem of yours.)
If you create an array with size 23, you can have indexes up to 22 (which is the highest indexed column of the ones that could be double clicked).
int[23] doubleClickConnections = new int[23];
Then, you should define only the indexes that have a double-click connection. So 2,6,10,14,18,22. Like this:
doubleClickConnections[2] = 5;
(There seems to be a pattern to your indexes. Your left side indexes are in the form 4n + 2, and your right side index is always 4n + 5. This could also be used, but I leave that to you.)
After you've done this, you should use the DataGridViewCellEventArgs class' properties, ColumnIndex and RowIndex. (They return the indexes of the double-clicked cell.):
int columnToModify = doubleClickConnections[e.ColumnIndex]; //if e.ColumnIndex is 2, this sets the variable to 5 for example.
int valueToAssign = (new object[] {null, 1}).Contains(
dataGridViewAcorn.Rows[e.RowIndex].Cells[e.ColumnIndex].Value
) ? 0 : 1;
dataGridViewAcorn.Rows[e.RowIndex].Cells[columnToModify].Value = valueToAssign;
This assumes the logic to enter 0 or 1 into the cell to modify is always the same (if the clicked cell is 0 it puts 1, if it is 1 it puts 0).
If you want to do the first part with a Dictionary<int, int> object:
Dictionary<int, int> doubleClickConnections = new Dictionary<int, int>(6) {
{ 2, 5 },
{ 6, 9 },
...
};
Then, you reference the dictionary the same way you would reference an array, e.g:
doubleClickConnections[2] //which equals 5

Problem with going to the next item in a list

The following pertains to C#
there are 4 lists:
INRHolidays list: Contains all the holidays and weekends
CashFlowDates: Containing all the dates for 10 years from today
CashFlowDatesFinal: Containing all the dates in CashFlowdates except the INRHolidays
TenorDates: Containing some specific dates i.e 6m, 9m, 12m, 1y, 2y, 3y, 4y, 5y, 7y, and 10y from now.
Now I want to check whether these specific dates in the TenorDates are Holidays or not. If not then they should be directly added to new list, HolidayAdjustedTenorDates, otherwise the next working day from CashFlowDates should be added.
20 is just a number as I didn't understand how to put the boundary condition.
var HolidayAdjustedTenorDates = new List<string>();
foreach (var a in TenorDates)
{
if (CashFlowDatesFinal.Contains(a))
{
HolidayAdjustedTenorDates.Add(a);
}
else
{
for (var i = 1; i < 20; i++)
{
if(CashFlowDatesFinal.Contains(
Convert.ToDateTime(a).AddDays(i).ToShortDateString()))
{
HolidayAdjustedTenorDates.Add(
Convert.ToDateTime(a).AddDays(i).ToShortDateString());
}
}
}
}
What is the exact problem, that you are not getting the right date or that you don't know how to write the loop, to put the boundary condition?
You may try a while loop:
int i = 1;
while(!CashFlowDatesFinal.Contains(Convert.ToDateTime(a).AddDays(i).ToShortDateString()))
{
i++;
}
HolidayAdjustedTenorDates.Add(Convert.ToDateTime(a).AddDays(i).ToShortDateString();
I cannot place a comment so sorry to post an answer but :
1-you should really improve your code. C# is a strong typed language, so avoid to use var, but use the real type instead
2-don't work directly on a, use temporarily variables.
This done, you could avoid mistakes and you can facilitate debugging.
For example, in your code, if CashFlowDatesFinal contains DateTime, you don't have to compare with string (made by ToShortDateString())

C# Unity3D - Get stuck with an sticky situation

Im making a game inside Unity3D but im stuck with something what I try to find the solution on it.
Its a part of a stock system where you can store things in it like "items or materials".
the following variables / classes are as follows :
[Serializable] public class ItemStorage
{
public ExtendedList.Items item;
public List<MaterialStorage> material;
}
[Serializable] public class MaterialStorage
{
public ExtendedList.Ingots material;
public int materialCount;
}
Above are the classes.
public List<ItemStorage> itemstorage;
public List<MaterialStorage> materialstorage;
Above are the variables.
and under this are the enums what i bassicly use :
public enum Items : int
{
[Description("Helmet")]
HELMET = 0,
[Description("Chestplate")]
CHESTPLATE = 4,
[Description("Platelegs")]
PLATELEGS = 8,
[Description("Gaunlets")]
GAUNLETS = 12,
[Description("Boots")]
BOOTS = 16,
[Description("Sword")]
SWORD = 20,
[Description("Shield")]
SHIELD = 24,
[Description("Wheel")]
WHEEL = 28,
[Description("Axe")]
AXE = 32
}
public enum Ingots : int
{
[Description("Bronze Ingot")]
BRONZE = 0,
[Description("Iron Ingot")]
IRON = 5,
[Description("Steel Ingot")]
STEEL = 10,
[Description("Silver Ingot")]
SILVER = 15,
[Description("Platinum Ingot")]
PLATINUM = 20
}
but I have a code where I call it in the "Awake" to initialize the / those list(s) :
for (int i = 0; i < Enum.GetValues(typeof(ExtendedList.Ingots)).Length; i++)
{
if (GameManager.Instance.PlayerLevel >= ExtendedList.GetIngotValue(i))
{
materialstorage.Add(new MaterialStorage() { material = (ExtendedList.Ingots)ExtendedList.GetIngotValue(i) });
}
}
for (int i = 0; i < Enum.GetNames(typeof(ExtendedList.Items)).Length; i++)
{
if (GameManager.Instance.PlayerLevel >= ExtendedList.GetItemValue(i))
{
itemstorage.Add(new ItemStorage() { item = (ExtendedList.Items)ExtendedList.GetItemValue(i), material = materialstorage });
}
}
On start it initializes as perfect. So at material list i get (bronze) and in the item list I get (helmet) but when I level up I call the function. So in the material list i get (bronze, bronze) and in the item list I get (helmet, helmet) instead of (bronze) and (helmet).\
edit :
(forgot) : when the player is level 0 it only initializes bronze. but when it reaches level 5 its adding a new list.
but than instead of bronze its iron.
so i want to add a new list when the player level is equalls to the value what i give to iron, steel, silver, platinum, etc.
I hope you guys can help me with this sticky situation.
Best wishes, And have a good day.
EDIT
I was slightly mistaken in how the dictionary was being populated, the reason you are seeing "1","2" is because of the values being inserted into the dictionary, not the key. Take this line you have:
for (int i = 0; i < Enum.GetValues(typeof(ExtendedList.Ingots)).Length; i++)
The variable i will loop from 0 -> 4, because you have 5 elements in ExtendedList.Ingots. That means that when the following bit of code is run:
int key = ExtendedList.GetLevel((ExtendedList.Ingots)i);
ExtendedList.Ingots value = (ExtendedList.Ingots)i;
levelToMaterialsMap.Add(key, value);
The variable value will only ever be BRONZE,1,2,3,4. This is because when you cast an integer to an enum as in the second line above, even if it doesn't find the value in your Enum set, the cast will still work but value will now equal to i , that's just how enums works in .NET. So in the first loop, the cast is (ExtendedList.Ingots)(0) -> BRONZE because it found the value 0 in the enum set. From the second iteration onward, it doesn't find the value so you get (ExtendedList.Ingots)(1) -> 1, (ExtendedList.Ingots)(2) -> 2 and so on.
I have found the solution of my problem with ur method (Sasang)
the the console is giving now the correct key / values.
in the for loop is everything the same except the line with calculating the value line.
the code looks right now like this :
ExtendedList.Ingots value = (ExtendedList.Ingots)Enum.GetValues(typeof(ExtendedList.Ingots)).GetValue(i);
The reason you are getting [bronze, bronze] at level2 in your materialstorage list (instead of just [bronze]) is because you are adding values to your list with materialstorage.Add, it seems to me that what you really want is to initialize a new list every time that method runs, so before you iterate through your enums in the for loops, set the materialstorage and itemstorage to new lists.
Also i dont entirely understand the reason for having materialstorage list defined twice if they always appear to be the same value. You have it defined at the gamemanager level and also again in each itemStorage object. If i understand your edit statement correctly, i seems like you want a list of lists where the number of lists is equal to the number of level increments like so:
0: [[bronze]]
5: [[bronze], [bronze,iron]]
10: [[bronze], [bronze,iron], [bronze,iron,steel]]
...
In this case what you really need is a Dictionary, one which maps player level to a separate list of materials. You can initialize this at the in your main GameManager class. Where the number of keys in the dictionary equals to the number of elements in your enum, like so:
Dictionary<int, List<MaterialStorage>> levelToMaterialsMap =
new Dictionary<int, List<MaterialStorage>>();
for (int i = 0; i < Enum.GetValues(typeof(ExtendedList.Ingots)).Length; i++)
{
int key = ExtendedList.GetIngotValue(i);
List<MaterialStorage> value = new List<MaterialStorage>();
levelToMaterialsMap.add(key, value);
}
Now every time you call your looping method, check to see if the player level is one of the levels in which you need to add materials for, if it is then create a new materialstorage list, add all the materials to it, then set it into the Dictionary for that specific level key. Something like:
if(levelToMaterialMap.containsKey(GameManager.Instance.PlayerLevel))
{
List<MaterialStorage> materialstorage = new List<MaterialStorage>();
//Do all the stuff you need to add materials for this player level
//...
//Then
levelToMaterialMap[GameManager.Instance.PlayerLevel] = materialstorage;
}

Increment through a list on a button list

I've stored a list of colors in my program. I am after an object in my scene to one of the colors in the list. So far, I have done the followings:
if(Input.GetKeyDown(KeyCode.O))
{
for(int i = 0; i < claddingColor.Count; i++)
{
claddingMaterial.color = claddingColor[i];
}
}
This isn't working due to a reason I know (and you can probably spot) but I lack to the verbal fortitude to write it down.
As opposed to have a multiple lines of the following:
claddingMaterial.color = claddingColor[0];
Each tied to different buttons, I like a way I can emulate the above but tie it to a single button press. Thus, if I hit the 0 button 5 times, it will loop through each color stored in the list. If I hit it for a sixth time, it will go back to the first color in the list.
Could someone please help me implement this? Or point me to something that I may learn how to do it for myself?
Define LastColor property as class member:
int LastColor;
In your function use modulo
if(Input.GetKeyDown(KeyCode.O))
{
claddingMaterial.color = claddingColor[(LastColor++) % claddingColor.Count];
}
Note: Depending on the type of claddingColor use Count for a List or Length for Array.
You won't need a for loop
int lastStep = 0;
if(Input.GetKeyDown(KeyCode.O))
{
claddingMaterial.color = claddingColor[lastStep++];
if (lastStep == claddingColor.Count)
lastStep = 0;
}

Swapping Objects in an Array - C#

In C#, I have an Array of MenuItem. I'm trying to swap the two Objects in index 2 and index 3 of the array without success using the code below:
MenuItem Temp = Items[2];
Items[2] = Items[3];
Items[3] = Temp;
There must be a reason why the second and third lines aren't working in C# which I may not understand yet. Is anyone able to clarify it a bit more? Do I have to go deeper and swap each property in the objects individually?
Edited - Sorry. Looks like I made a mess of the code when trying to clean it up for posting. Corrected now.
The actual code is :
MenuItem TempButton = MenuItems.Items[SelectedButton.CountId];
MenuItems.Items[SelectedButton.CountId] = MenuItems.Items[SelectedButton.CountId + 1];
MenuItems.Items[SelectedButton.CountId + 1] = TempButton;
MenuItems.Items is an array of MenuItem
Looking at the Watch I have placed on MenuItems.Items, nothing happens on Line 2 or 3.
The MenuItems.Items property has get and set functions, which may be causing the issue... Will investigate further...
You are settings Items[2] to Temp, which was Items[2] to begin with, so you are effectively not doing anything. I don't know what SelectedButton.CountId is supposed to be.
But if you just want to swap indices 2 and 3, you can do this:
Item Temp = Items[2];
Items[2] = Items[3];
Items[3] = Temp;
Is SelectedButton.CountId = 2? if so I would try this:
Item Temp = MenuItems.Items[2];
MenuItems.Items[SelectedButton.CountId] = MenuItems.Items[3];
MenuItems.Items[3] = Temp;
Note the last line has a 3 in it.
This would be clearer:
Item Temp = MenuItems.Items[SelectedButton.CountId];
MenuItems.Items[SelectedButton.CountId] = MenuItems.Items[3];
MenuItems.Items[3] = Temp;
I have no idea what SelectedButton.CountId is supposed to be but you're putting Temp right back in the same slot it was to begin with. And MenuItems.Items seems to be a totally different collection from Items.
string[] items = { "one", "two", "three" };
string temp = items[1]; // temp = "two"
items[1] = items[2]; // items[1] = "three"
items[2] = temp; // items[2] = "two"
// items is now
// { "one", "three", "two" }
try:
Item Temp = Items[SelectedButton.CountId];
Items[SelectedButton.CountId] = MenuItems.Items[SelectedButton.CountId+1];
Items[SelectedButton.CountId+1] = Temp;
This should swap in a bubble fashion
I remember running into a similar source of confusion some time ago, with the DataRow.ItemArray property. This property was extremely counterintuitive for the very same reason that the Items property in your example seems so odd.
What was ultimately so confusing was that the property was designed to be copied from and assigned to, just like you normally would with a field of value type (like int, double, etc.). That is, to change the element at index 2, this would not work:
row.ItemArray[2] = "New Value";
The above code would essentially copy the values from the row into a new array, take that copy and set the value at index 2 to "New Value," and then the new array would immediately be out of scope. The way this property was supposed to work was:
object[] items = row.ItemArray;
items[2] = "New Value";
row.ItemArray = items;
Very counterintuitive, in my book (note to library developers: don't do this). But it sounds like this is probably the problem behind the issue you were seeing with your code.
In other words, I think the swapping code you have (now) is correct. The problem lies with whoever had the bright idea of making that Items property behave as if it's a value field.
I had the same problem as I wanted to move elements in a WPF-TreeView up and down. Since none of the answers solved the problem for me here is the best I could find.
private void MoveLayerUp()
{
if(Layers.SelectedItem != null)
{
int index = Layers.Items.IndexOf(Layers.SelectedItem);
if (index > 0)
{
var swap = Layers.Items[index - 1];
Layers.Items.RemoveAt(index - 1);
Layers.Items.Insert(index, swap);
}
}
}
private void MoveLayerDown()
{
if (Layers.SelectedItem != null)
{
int index = Layers.Items.IndexOf(Layers.SelectedItem);
if (index < Layers.Items.Count-1)
{
var swap = Layers.Items[index + 1];
Layers.Items.RemoveAt(index + 1);
Layers.Items.Insert(index, swap);
}
}
}
This solves the problem of assigning elements in the collection. Further it has the advantage that the current seleced item is never touched and stays selected.
Solved the issue. I think I complicated the problem a bit too much.
MenuItems.Items was a property with get/set functions that returns/sets a private ArrayList.
I created a function in the class for MenuItems which swapped the indexes in the private ArrayList. (which used standard swapping code similar to what I tried and what everyone has mentioned in their replies.)
Thanks for everyone's help.

Categories