Finding an item by object value in Combobox - c#

I have a combo box that is populated with an Arraylist, like below. If I have another instance of same object, how do I select that object in the combobox? Please look at the code below to understand.
MakeEntity selectedMake = Make.GetMakeByTitle("Honda");
List<MakeEntity> allMakes = Make.GetAllMakes();
cbVehicleMake.DataSource = allMakes;
cbVehicleMake.SelectedIndex = cbVehicleMake.Items.IndexOf(selectedMake);
But last line is not working as expected. Can I get it to run at all or am I going in the wrong direction? Should MakeEntity implement iComparable?

Assuming MakeEntity has an property called id!
cbVehicleMake.SeletedItem=allMakes.Find(q=>q.Id==selectedMake.Id))

You shouldn't need to implement IComparable for IndexOf, just Equals. Otherwise it will default to Object.Equals, which only matches if the two references are to the same instance. (Not sure if this is a problem or not without seeing the definition of MakeEntity.)
Also, just use:
cbVehicleMake.SelectedItem = selectedMake;
This will internally handle finding the object in the options.
Documentation: http://msdn.microsoft.com/en-us/library/system.windows.forms.combobox.selecteditem.aspx

Related

C# iterate generic object

Am moving from Excel VBA to VSTO using C#. In VBA I had a 3 line custom function called IsInCollection as shown below:
On Error Resume Next
Set obj = collectionObject(itemObject)
IsInCollection = Not (obj is Nothing)
I used it all the time to check if a given workbook was open, or if a workbook contained a sheet with a particular name, etc. Because the collection and the item arguments are defined as objects it would work with anything.
I'm trying to create the same utility function/method in managed code and am struggling mightily. The problem is with the collectionObject(itemObject) expression. C# doesn't allow me to just index an object as VBA did.
If anybody can point me in the right direction it would be much appreciated. From my searching I've been looking into QueryInterface but am not sure if that's where I should be looking. It seems that an Excel object comes across as a System._ComObject, so presumably I need to iterate through that somehow(?).
TIA
i think you want to check out LINQ. for example you can query collections like
IsInCollection = obj.Any(s => s != null);
The indexing operator in C# is [], not () as in VB. I'm not very familiar with COM though, so if the object you have is just an object/System._ComObject you might have to cast it to the appropriate type first, unless _ComObject has an indexer already.
It seems that finding out what type a _ComObject really is can be be a bit difficult, so you might wanna try a trick I found at http://www.mztools.com/articles/2006/mz2006013.aspx:
var typeName = Microsoft.VisualBasic.Information.TypeName( collectionObject );
I also suspect you could use the System.ComponentModel.TypeDescriptor class.

Dynamically setting type or result from invoked generic method?

My apologies if the question is somewhat unclear; I'm not entirely certain how to phrase this.
My issue is this. I have two classes, Manager<T> and Result<T>. Within Manager<T>, I have a whole raft of retrieval functions. Ordinarily, I would call Manager<T> and set its type like so:
Manager<SpecialDataType> mgr = new Manager<SpecialDataType>;
After which I set up my Result type, and fill it with my function from Manager, where 1 is a parameter for the GetItem function shown. I can then access things in my item:
Result<SpecialDataType> item = new Result<SpecialDataType>;
item = mgr.GetItem(1);
string x = item.Teaser;
OK. So now, what I'm trying to do is set the <SpecificDataType> to be filled in at run time. I think I've got half of the solution already, using generic types, like so:
Type generalType= Type.GetType("SpecificDataType");
Type managerType= typeof(Manager<>).MakeGenericType(generalType);
var managerInstance= Activator.CreateInstance(managerType);
object[] args = {1};
MethodInfo getItemMethod = managerInstance.GetMethod("GetItem");
But here's where I get stuck. There are specific properties that my Result class has that I need to be able to access. They are, or course, set by the data type I'm casting into. When I do an Invoke, like so:
var item = getItemMethod.Invoke(managerInstance, args);
I'm not getting any of my properties that I know are part of item. That makes sense, I suppose, because we don't know what item is. So, we tried this:
Type dataType = typeof(SmartFormData<>).MakeGenericType(sfType);
var item = Activator.CreateInstance(dataType);
item = getItemMethod.Invoke(managerInstance, args);
And got the same result. I can't seem to get to item.Teaser.
I'm not a c# coder natively (as though that's not apparent already from this overly complicated question I'm asking), so I'm not incredibly familiar with reflection and generic types. Can anyone point me in the right direction for how to solve this problem, or how to approach it from a different angle? The only caveat is that I cannot modify the Manager<T> and Result<T> functions; I have to use what I'm given there.
Thanks in advance for any help you can offer.
As Dark Falcon correctly notes in his comment you will have to use reflection to get the members of your item.
Or, if you are in .NET 4 or above, you can use the dynamic keyword to greatly simplify things:
Type generalType= Type.GetType("SpecificDataType");
Type managerType= typeof(Manager<>).MakeGenericType(generalType);
dynamic managerInstance = Activator.CreateInstance(managerType);
var item = managerInstance.GetItem(1);
string x = item.Teaser;
You need to cast the invocation result to the type you're expecting
var item = (Result<SpecificDataType>)getItemMethod.Invoke(managerInstance, args);

Modifying LinkedListNode property in C#

I'm working with LinkedList in C#.
All I want to do is a simple code that excludes B from the list and directly connect node A with B.Next:
A.Next = B.Next;
B.Next.Previous = A;
But got an error:
Property or indexer System.Collections.Generic.LinkedListNode<>.Next
cannot be assigned to it is read only.
Is it possible to somehow get the right to assign values to Next and Previos properties?
Or how can I avoid this error?
Best regards.
You can just call LinkedList<T>.Remove and pass in B. The Remove method takes care of this for you.

Calling Equals returns false every time, even when values are same (C#)

I have a problem in an Windows Forms application which uses a XNA screen. I want to see if a change happens to an object after completing multiple lines of code. If it does, it should add a * to the Title to tell the user the file did changes but hasn't saved.
To do that, I copy the object and after those lines I check if they are equal.
MapSquare afterChange = TileMap.GetMapSquareAtPixel((int)mouseLoc.X,(int)mouseLoc.Y);
MapSquare beforeChange = (MapSquare)afterChange.Clone();
// code.....
if (!Object.Equals(beforeChange,afterChange))
parentForm.MapChanged = true; // this happens even when no changes happend
This mistake must be in my Clone Method I used with the Iclonable interface because even when I check equals right after copying it, it doesn't work.
public object Clone()
{
return new MapSquare(this);
}
private MapSquare(MapSquare squere)
{
this.LayerTiles = (int[])squere.LayerTiles.Clone();
this.CodeValue = squere.CodeValue;
this.Behavior = squere.Behavior;
}
What's the mistake? I think it's in the layertiles array but I already tried many things there, so I don't know what to do. Or is there even a other much easier way to solve my problem?
You would need to override Object.Equals for your MapSquare type to make it compare equality based on the values. By default, Object.Equals only returns true if the two variables refer to the same actual instance - not if they have the same member values.
If you plan to do this, I would recommend implementing IEquatable<MapSquare>, as well.
Unless you overload the equality operator, you are testing whether the two object references are equal, not whether they contain identical values.

Removing from list recursively in C#

I have the following recursive function that is used to search down a hierarchical tree and remove found objects from a list:
private List<Tag> RemoveInvalidTags(Device device, List<Tag> tags)
{
var childDevices = device.ChildDevices.Select(c => c.ChildDevice);
foreach (var child in childDevices)
{
tags.Remove(child.Tag);
RemoveInvalidTags(child, tags);
}
return tags;
}
What I am expecting this to do is remove all child device tags at this level from the tags list, call the function recursively for your children, then return that list up to the previous level.
Will this pass the tags list by reference and modify the original passed list? Or should I be doing something along the lines of
validTags = CollectValidTags(child, tags);
and adding up all the returned lists?
Will this pass the tags list by reference
No. The list object is passed "by value" (but see next). (ref or out is required to "pass by reference" in C#, but that is not being done here, nor does it need to be.)
and modify the original passed list?
Yes. This is because the list object is passed. And that list object is mutated. Passing a reference type (anything defined with class) never implicitly makes a copy/clone/duplicate. An object is what it is.
Now, back to "pass by value": the "value passed" is the value of the "reference" (internal, no need to concern with this): this calling strategy is better known as Call/Pass By Object Sharing in a langauge like C#. The same object is shared (just as if it were assigned to two different variables). (Value types -- a struct -- are different in that they (often) are copied/duplicated on the stack, but a List<T> is a class.)
Or should I be doing something along the lines of
It depends upon the desired semantics. Is the caller expecting the side-effects directly or indirectly? Can the mutation side-effect lead to unexpected scenarios? Make sure to document it either way. (I prefer the way that guarantees the initial object is not mutated.)
Hope that clears some things up.
Happy coding.
In your code you are modifying the items in your tags parameter and passing back the modified list as your result. You want to avoid modifying lists in this way - especially inside loops where it can cause you grief in many situations.
I have a LINQ-based alternative for you.
If I understand the intent of your code you want to do something like this:
Func<Device, IEnumerable<Device>> flatten = null;
flatten = d =>
{
return (new [] { d }).Concat(
from c in d.ChildDevices
from f in flatten(c)
select f);
};
var collectedValidTags = flatten(device).Select(d => d.Tag);
var result = tags.Except(collectedValidTags).ToList();
This approach doesn't pass your list of tags around so there is no chance of modifying your original list.
Does this help?
Short answer - your code will do what you want.
Long answer - you should read descriptions of what the ref keyword does. I would suggest you read as many descriptions as possible; there are many different ways to articulate it ("I like to think of it as... ") and some will work for you whilst others won't. If you read many descriptions (from people who understand it) then some kind of understanding should gel for you.
Here's a list to get you started:
Use of 'ref' keyword in C# (my answer)
C# ref keyword usage
Passing by ref?
Example of practical of "ref" use

Categories