I've seen a couple questions about this, and done some research.
My understanding is that when you run a foreach on IEnumerable: if T is a Reference Type (e.g. Class) you should be able to modify properties of the object from within the loop. If T is a value type (e.g. Struct) this would not work since the iteration variable would be a local copy.
I am working on a Windows Store app with the following code:
My Class:
public class WebResult
{
public string Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string DisplayUrl { get; set; }
public string Url { get; set; }
public string TileColor
{
get
{
string[] colorArray = { "FFA200FF", "FFFF0097", "FF00ABA9", "FF8CBF26",
"FFA05000", "FFE671B8", "FFF09609", "FF1BA1E2", "FFE51400", "FF339933" };
Random random = new Random();
int num = random.Next(0, (colorArray.Length - 1));
return "#" + colorArray[num];
}
}
public string Keywords { get; set; }
}
The Code:
IEnumerable<WebResult> results = from r in doc.Descendants(xmlnsm + "properties")
select new WebResult
{
Id = r.Element(xmlns + "ID").Value,
Title = r.Element(xmlns + "Title").Value,
Description = r.Element(xmlns +
"Description").Value,
DisplayUrl = r.Element(xmlns +
"DisplayUrl").Value,
Url = r.Element(xmlns + "Url").Value,
Keywords = "Setting the keywords here"
};
foreach (WebResult result in results)
{
result.Keywords = "These, are, my, keywords";
}
if (control is GridView)
{
(control as GridView).ItemsSource = results;
}
Once the results get displayed the "Keywords" property is "Setting the keywords here". If I put a break point in the foreach loop I can see that the results object is not getting modified...
Any ideas as to what is going on? Am I just missing something obvious? Does IEnumerable behave differently in .NET For Windows Store Apps?
This is known as deferred execution; results is a query that is executed every time you iterate over it. In your case it's evaluated twice, once in the for loop, and a second time when it's databound.
You can verify this by doing something like this
var results2 = results.ToList();
foreach (WebResult result in results2)
{
result.Keywords = "These, are, my, keywords";
}
if (control is GridView)
{
(control as GridView).ItemsSource = results2;
}
You should see that your changes persisted.
Related
I try to code a Storagesystem and i got one Problem and dont know how to solve it...
public static List<string> GetAllItemsFromDB(string Searchbar)
{
List<string> retList = new List<string>();
retList.Clear();
var filter = Builders<DB_Package_Item>.Filter.Eq(Item => Item.Item_Name, Searchbar);
var ItemsMatch = Item_DB.Find(filter).ToList();
foreach (var Item in ItemsMatch.ToList())
{
retList.Add(Item.Item_Name);
}
return retList;
}
This Works. But when i change the filter to:
var filter = Builders<DB_Package_Item>.Filter.ElemMatch(Item => Item.Item_Name, Searchbar);
It crasches as soon i type any char in the searchbar with Error code : "System.InvalidOperationException: "The serializer for field 'Item_Name' must implement IBsonArraySerializer and provide item serialization info."
"
I just dont get it why...
This is the Data_Package for MongoDB
public class DB_Package_Item
{
public Guid Id { get; set; }
public int Item_ID { get; set; }
public int Box_ID { get; set; }
public string Item_Name { get; set; }
public int Quantity { get; set; }
public string Partnumber { get; set; }
public string Supplier { get; set; }
}
Thx for every help!
FilterDefinitionBuilder<TDocument>.ElemMatch<TItem> or $elemMatch operator is for searching the item in the array field, which is not appropriate for your scenario to search (term) for a string field.
You need the $regex operator which is FilterDefinitionBuilder<TDocument>.Regex in C# syntax.
using System.Text.RegularExpressions;
var filter = Builders<DB_Package_Item>.Filter.Regex(Item => Item.Item_Name
, new Regex("^" + Searchbar));
For case-insensitive:
new Regex("^" + Searchbar, RegexOptions.IgnoreCase)
Or
var filter = Builders<DB_Package_Item>.Filter.Regex(Item => Item.Item_Name
, new BsonRegularExpression("^" + Searchbar));
For case-insensitive,
new BsonRegularExpression("^" + Searchbar, "i")
Good day,
I have a RavenDB JSON Document in which one field ("Info") contains a string that looks like this:
"{\"value1\":\"9\", \"value2\": \"dog\", ....}"
I would like to remove the escaping "\" characters so it will be recognized as a JSON List by RavenDB.
However, I have tried updating the Documents with
newString = oldString.Replace("\\", "") ,
newString = oldString.Replace(#"\", "")
and newString = oldString.Trim(new Char[] { #"\" })
but it does not work. After applying these above mentioned methods the string looks unchanged.
Please see below the full code:
while(true)
{
var result = session.Query<Documents>()
.Take(1000).Skip(i)
.ToList();
if (result.Count == 0)
break;
foreach (var r in result)
{
string rInfo = r.Info.ToString();
rInfo = rInfo.Replace("\\", "");
PATCHED_Doc r_Doc = new PATCHED_Doc()
{
Info = rInfo,
Value = "test",
Id = r.Id,
Date = r.Date,
};
session.Store(r_Doc);
session.SaveChanges();
}
session.SaveChanges();
i += result.Count;
}
public class PATCHED_Doc
{
public string Info { get; set; }
public string Value { get; set; }
public int Id { get; set; }
public string Date { get; set; }
}
Thank you in advance for helping.
You need to Parse the JSON into an object and then hand it over to Raven DB. Strings are treated as strings. Use JSON.NET library to parse it into Anonymous objects. Change your Info property to type of object. Then Assign the anonymous object to the Info property.
I have an array in C#:
string[] foo = new string[11];
The length of foo array has been 10, I only changed it to 11 because I needed an extra value. My only problem is: I can't seem to change the length of the array. If I change it to 11, like in the above example, set a break point and debug, after the compiler passes this line, it still has a length of 10.
Now when I add a watch foo = new string[11] after the compiler passes this line, all the values are erased and the length is changed to 11. Basically I have no idea what is going on, especially why adding a watch has an effect on the runtime values of variables.
Does anybody have any idea what is happening here?
public string[] getValues()
{
//Why does this only have 10 dimensions after initialization?????
string[] values = new string[11];
string[] temp = ddlProjectnumber.Text.Split('-'); //<----- here I set break point.
values[0] = temp[0].Trim();
values[1] = tbTask.Text;
values[2] = ddlSubstitute.Text;
values[3] = ddlCategory.Text;
values[4] = ddlSubcategory.Text;
values[5] = cbFinished.Checked.ToString();
if (propertychanged)
{
values[6] = DateTime.Now.ToString();
}
values[7] = cbJourney.Checked.ToString();
return values;
}
Your code will be easier to maintain if you create a class to hold your values:
public class MyClass
{
public string ProjectNumber { get; set; }
public string Task { get; set; }
public string Substitute { get; set; }
public string Category { get; set; }
public string Subcategory { get; set; }
public bool Finished { get; set; }
public DateTime? PropChangedDate { get; set; }
public bool Journey { get; set; }
}
Then adjust your method to just populate an instance of the class and return that instead:
public MyClass GetValues()
{
var myClass = new MyClass
{
ProjectNumber = ddlProjectnumber.Text.Split('-').First().Trim(),
Task = tbTask.Text,
Substitute = ddlSubstitute.Text,
Category = ddlCategory.Text,
Subcategory = ddlSubcategory.Text,
Finished = cbFinished.Checked,
Journey = cbJourney.Checked
};
if (propertychanged)
myClass.PropChangedDate = DateTime.Now;
return myClass;
}
Now you don't have to guess which values were stored in each element of the array.
okay I played around a bit and after changing my configuration from debug to release and then to debug again, it apparently fixed itself. I guess it really was old code, but for some reason, it did not recompile correctly after I cleaned and rebuild my solution. anyway it works now :)
I have this structure of classes:
public class L3Message
{
public int Number { get; set; }
public string MessageName { get; set; }
public string Device { get; set; }
public string Time { get; set; }
public string ScramblingCode { get; set; }
public List<Parameter> Parameters { get; set; }
public L3Message()
{
Parameters = new List<Parameter>();
}
}
public class Parameter
{
public int numOfWhitespaces { get; set; }
public string ParameterName { get; set; }
public string ParameterValue { get; set; }
public Parameter Parent { get; set; }
public List<Parameter> SubParameters { get; set; }
public Parameter()
{
SubParameters = new List<Parameter>();
}
}
So, as return type from one of my Methods I have List of L3Messages (List<L3Message>), and I need to map that to TreeView in WinForms (populate TreeView from that List).
EDIT:
Please notice that tree of my objects can be deeper than one level (becouse class Parameter have prop List < Parmaeter > (List of Parameter object, same structure as root parameter object)), so that means recursion or something like.
EDIT2:
Here is pic of tree, but this tree is created from text file base on whitespaces, so here is all Parameters, in my tree I need only one from List of L3Message objects.
http://imageshack.us/photo/my-images/803/treeviewmessage.png/
EDIT3:
I'm sure that my TreeView need to be something like this:
L3Message.Number: L3Message.MessageName
+L3Message.Time
+L3Message.Device
+L3Message.ScramblingCode
+L3Message.Parameters[0]
++Parameter.ParamaeterName: Parameter.ParameterValue
++ (same as above)
L3Message.Number: L3Message.MessageName
+L3Message.Time
+L3Message.Device
+L3Message.ScramblingCode
+L3Message.Parameters[0]
++Parameter.ParamaeterName: Parameter.ParameterValue (in this occasion Value is null )
+++SubParameter.ParameterName: SubParameter.ParameterValue
Something like that
If possible, I would like to that in separate thread.
How can I achieve that?
Of course it is possible. Now it depends how you want your TreeView to be structured. Then you just need to create TreeNode objects and add them to the TreeView. See this small tutorial: http://www.dotnetperls.com/treeview
If you are going to do this on a different thread, you will need to update the GUI by forwarding the updates to the GUI thread using BeginInvoke:
TreeNode node = new TreeNode("node");
L3Message msg = new L3Message();
node.Tag = msg;
treeView.BeginInvoke(
(Action)(() =>
{
treeView.Nodes.Add(node);
}));
Notice that the TreeNode needs to be created with a string representing the name and then you can add the object it points to using the Tag property.
I managed to solve this, but I think that is not optimize and there is no separate thread.
If anyone can modify my code to perform better and add separate thread?
SOLUTION:
foreach (L3Message message in por)
{
treeViewMessages.Nodes.Add(message.Number + ": " + message.MessageName);
treeViewMessages.Nodes.Add("Time: " + message.Time);
treeViewMessages.Nodes.Add("MS: " + message.Device);
treeViewMessages.Nodes.Add("Scrambling Code: " + message.ScramblingCode);
foreach (Parameter param in message.Parameters)
{
TreeNode tnRootParam = new TreeNode();
//tnRootParam.Nodes.Add(param.ParameterName + ": " + param.ParameterValue);
if (param.SubParameters.Count != 0)
{
CreateTreeNodes(param, tnRootParam);
tnRootParam.Text = param.ParameterName;
treeViewMessages.Nodes.Add(tnRootParam);
}
else
{
tnRootParam.Text = param.ParameterName + ": " + param.ParameterValue;
treeViewMessages.Nodes.Add(tnRootParam);
}
}
treeViewMessages.Nodes.Add("---------------------------------------------------------------------");
}
private void CreateTreeNodes(Parameter parameter, TreeNode tnRootParam)
{
if (parameter.SubParameters.Count == 0)
{
tnRootParam.Nodes.Add(parameter.ParameterName + ": " + parameter.ParameterValue);
}
else
{
foreach (Parameter subparam in parameter.SubParameters)
{
CreateTreeNodes(subparam, tnRootParam);
}
}
}
I have the following classes:
public class Person
{
public String FirstName { set; get; }
public String LastName { set; get; }
public Role Role { set; get; }
}
public class Role
{
public String Description { set; get; }
public Double Salary { set; get; }
public Boolean HasBonus { set; get; }
}
I want to be able to automatically extract the property value diferences between Person1 and Person2, example as below:
public static List<String> DiffObjectsProperties(T a, T b)
{
List<String> differences = new List<String>();
foreach (var p in a.GetType().GetProperties())
{
var v1 = p.GetValue(a, null);
var v2 = b.GetType().GetProperty(p.Name).GetValue(b, null);
/* What happens if property type is a class e.g. Role???
* How do we extract property values of Role?
* Need to come up a better way than using .Namespace != "System"
*/
if (!v1.GetType()
.Namespace
.Equals("System", StringComparison.OrdinalIgnoreCase))
continue;
//add values to differences List
}
return differences;
}
How can I extract property values of Role in Person???
public static List<String> DiffObjectsProperties(object a, object b)
{
Type type = a.GetType();
List<String> differences = new List<String>();
foreach (PropertyInfo p in type.GetProperties())
{
object aValue = p.GetValue(a, null);
object bValue = p.GetValue(b, null);
if (p.PropertyType.IsPrimitive || p.PropertyType == typeof(string))
{
if (!aValue.Equals(bValue))
differences.Add(
String.Format("{0}:{1}!={2}",p.Name, aValue, bValue)
);
}
else
differences.AddRange(DiffObjectsProperties(aValue, bValue));
}
return differences;
}
If the properties aren't value types, why not just call DiffObjectProperties recursively on them and append the result to the current list? Presumably, you'd need to iterate through them and prepend the name of the property in dot-notation so that you could see what is different -- or it may be enough to know that if the list is non-empty the current properties differ.
Because I don't know how to tell if:
var v1 = p.GetValue(a, null);
is String FirstName or Role Role. I have been trying to find out how to tell if v1 is a String such as FirstName or a class Role. Therefore I won't know when to recursively pass the object property (Role) back to DiffObjectsProperties to iterate its property values.