How to set one ObservableCollection to another ObservableCollection? - c#

Basically, I want to know if I can do this with two ObservableCollections:
oldList = newList;
I have two lists that get populated throughtout my app, and each time they get populated, I want the 'new' values to become the 'old' values, and then get a new set of values to put in the 'new' list.
is it that easy? Any other way to do this without iterating over the whole newList every time?
EDIT: This is how the new list is being populated. Basically, I just want the contents of the newList to be put into the oldList.
foreach (object obj in ts.GetVariables())
{
if ((obj.ToString() != "_SMSTSReserved2") || (obj.ToString() != "OSDJoinPassword") || (obj.ToString() != "OSDLocalAdminPassword"))
{
TSVar var = new TSVar();
var.TSVarName = obj.ToString();
var.TSVarValue = ts[obj.ToString()];
newList.Add(var);
}
}
oldList.Clear();
foreach (TSVar var in newList)
{
oldList.Add(var);
}

If you use the extension method listed below, what you are trying to do becomes a one liner:
oldList.Replace(newList);
I would create an Extension Method for ObservableCollection like this:
public static class ObservableCollectionExtensionMethods
{
public static void Replace<T>(this ObservableCollection<T> old, ObservableCollection<T> #new)
{
old.Clear();
foreach (var item in #new)
{
old.Add(item);
}
}
}
And this is how you would use it:
using System.Collections.ObjectModel;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace ExtensionMethods
{
[TestClass]
public class ObservableCollectionExtensionMethodsTest
{
[TestMethod]
public void ReplaceTest()
{
// Arrange
var old = new ObservableCollection<string> { "1"};
var #new = new ObservableCollection<string> {"2"};
// Act
old.Replace(#new);
// Assert
Assert.AreEqual("2", old.First());
}
}
}

I think this is what you may be looking for? This will add everything that was in newList to your oldList.
ObservableCollection<YourType> oldList = new ObservableCollection<YourType>(newList);
newList.clear();
//put new stuff in your list here.

Related

Initialize get-only collection in object initializer from existing collection

I have a class with a get-only collection property. I would like to initialize the collection with the values from an existing collection.
I know that it is possible to initialize the collection using a collection initializer. I could also create the object and then use AddRange on the collection to add the items of the existing collection. This would however create the object with an empty list and add the existing items afterwards.
Is there a way to create the object with the List properly initialized in the first place (without adding a constructor, of course)?
using System.Collections.Generic;
namespace EmptyConsoleApp
{
internal class Program
{
public static void Main(string[] args)
{
// Compiles, but is not what I need
var firstHolder = new Holder()
{
TheList = {"A", "B"}
};
// Compiles, but initializes the list after object creation
var existingList = new List<string>() {"Foo", "Bar"};
var secondHolder = new Holder();
secondHolder.TheList.AddRange(existingList);
// Does not compile
var thirdHolder = new Holder()
{
TheList = {existingList}
};
}
}
internal class Holder
{
public Holder()
{
TheList = new List<string>();
}
public List<string> TheList { get; }
}
}
No. You can't assign this read-only property from a collection initializer. It is read-only after all.
TheList = { "A", "B" } works since it calls Add on TheList (once for each item added), it doesn't create and assign a new instance, which it is not allowed to.
TheList = { existingList } doesn't work since there is a typing issue (TheList = { existingList[0] } does work).
The best option you have it to create a constructor parameter and drop your idea of using collection initializers for something it isn't fit for.
Is there a way to create the object with the List properly initialized in the first place (without adding a constructor, of course)?
No
It's not. That's what a constructor does. If you don't want to do it in the constructor, there is no way to do it.
it is not possible to initialize a read only property from outside of the class itself.
collection initializer is just a simplified syntax version and it does not mean using this syntax you have the same access as if you are in the class constructor
thirdHolder.TheList = existingList; // this is the traditional way
Perhaps you can use factory class pattern like this
internal class Program
{
public static void Main(string[] args)
{
// Compiles, but is not what I need
var firstHolder = new Holder()
{
TheList = { "A", "B" }
};
// Compiles, but initializes the list after object creation
var existingList = new List<string>() { "Foo", "Bar" };
var secondHolder = new Holder();
secondHolder.TheList.AddRange(existingList);
// Does not compile
//var thirdHolder = new Holder()
//{
// TheList = existingList
//};
//thirdHolder.TheList = existingList; // this is the traditional way
var thirdHolder = Holder.HolderFactory(existingList);
}
}
internal class Holder
{
public Holder()
{
TheList = new List<string>();
}
public static Holder HolderFactory(List<string> theList)
{
return new Holder(theList);
}
private Holder(List<string> theList)
{
this.TheList = theList;
}
public List<string> TheList { get; }
}

quick way to update in lambda expression

Here is how I get data from database and update using lambda expression .
item _myItem = db.myDBContext.items.Where(x => x.id == 0).SingleOrDefault();
_myItem.field1 = "myValueForField1";
_myItem.field2 = "myValueForField2";
_myItem.field3 = "myValueForField3";
_myItem.field4 = "myValueForField4";
db.myDBContext.SubmitChanges();
It's just a sample, my table has many columns.
If I follow this way, I have to assign each column (field1,field2,..).
If I have 20 columns, I have to write 20 lines of code.
Can I assign field name dynamically ?
Like
_myItem[dynamicFieldName] = ...;
Or is there any way to make it better ?
I just want to assign the field names dynamically.
Without using reflection, you cannot assign fields dynamically in that way.
Using reflection, you can, but there is a performance hit associated.
for example:
var myField = "field1";
var field = _item.GetType().GetField(myField); // perhaps GetProperty() - depending on if its a field or a property.
field.SetValue(_item,"myValueForField1");
Obviously that can be done in a loop, with all your field names in an array or list of some sort.
Try this one:
item _myItem = db.myDBContext.items.Where(x => x.id == 0).SingleOrDefault();
var typ = typeof(item);
typ.GetProperties().ToList().Foreach(m=> m.SetValue(_myItem,"yourvalue", null));
db.myDBContext.SubmitChanges();
You can use reflection:
PropertyInfo pInfo = _myItem.GetType().GetProperty("field2"):
pInfo.SetValue(_myItem, "myValueForField2");
You can not use reflection.
You would make indexer in your Item class. And use extension methods to convert to specific type.
using System;
using System.Collections.Generic;
namespace ConsoleApplication1
{
static class MyExtensions
{
public static int toInt32(this string field)
{
return Convert.ToInt32(field);
}
}
class MySpecificList
{
Dictionary<string, string> _fields = new Dictionary<string, string>();
public string this[string name]
{
get
{
return _fields[name];
}
set
{
_fields[name] = value;
}
}
static void Main(string[] args)
{
MySpecificList list = new MySpecificList();
list["field1"] = "1";
Console.WriteLine(list["field1"].toInt32() + 1);
}
}
}

Cast IEnumerable to custom ObservableCollection Class?

Is it possible to convert IEnumerable to a Custom Class that is inherting from ObservableCollection class?
Reason is I want to select only a filtered set of items on the get. I want to implement it on the get because lots of other properties reference CustomItems and perform processes on the items, but I want to somehow make it process filtered set of items depending if a value is enabled or not.
Below is code to help explain what I want to achieve:
public class CustomItemsCollection : ObservableCollection<ItemViewModel>
{
public ListView ListView { get; set; }
public void ScrollToItem(object item = null)
{
//Some custom Code
}
}
And here is my property that I want to customize:
private CustomItemsCollection _CustomItems = null;
[JsonProperty]
public CustomItemsCollection CustomItems
{
get
{
if (_CustomItems != null)
{
if(SomeValueIsEnabled)
{
var filteredItems = _CustomItems.Where(c => c.Property.equals(SomeValue));
var castedItems = (CustomItemsCollection)filteredItems;
return castedItems;
}
return _CustomItems;
}
_CustomItems = new CustomItemsCollection();
_CustomItemsChangedSource = new CollectionChangedWeakEventSource();
_CustomItemsChangedSource.SetEventSource(_CustomItems);
_CustomItemsChangedSource.CollectionChanged += _CustomItemsChangedSource_CollectionChanged;
return _CustomItems;
}
set { _CustomItems = value; RaisePropertyChanged("CustomItems"); }
}
Specifically, this part:
if(SomeValueIsEnabled)
{
var filteredItems = _CustomItems.Where(c => c.Property.equals(SomeValue));
var castedItems = (CustomItemsCollection)filteredItems;
return castedItems;
}
Is this possible / or maybe wrong? What is the best practice to do it?
Thank you!
You can't just cast it, but you can create an instance of CustomItemsCollection and initialize it with filteredItems.
Add a constructor to your custom class that passes through to the appropriate ObservableCollection constructor:
public class CustomItemsCollection : ObservableCollection<ItemViewModel>
{
public CustomItemsCollection(IEnumerable<ItemViewModel> items)
: base(items) { }
// your other code here
}
Then you can do this:
var filteredItems = _CustomItems.Where(c => c.Property.equals(SomeValue));
var collection = new CustomItemsCollection(filteredItems);
return collection;
Try with this code:
var filteredItems = _CustomItems.Where(c => c.Property.equals(SomeValue))
.Select(pre=> new ItemViewModel(){
//add info here
});
var castedItems = new CustomItemsCollection(filteredItems);

When to use generics and type checking?

Assume A through Z to be 26 classes I defined. In the following example:
private List<A> _listA;
private List<B> _listB;
// private List<C>, and so on, through...
private List<Z> _listZ;
private void setLabelA()
{
LabelA.Text = _listA.Count;
}
// private void setLabelB() exists
// and so does setLabelC()
// and so on, all the way through to...
private void setLabelZ()
{
LabelA.Text = _listZ.Count;
}
It seems to me that there is no way to shorten this other than the following:
private void setLabel<genericType>(List<genericType> list)
{
if(list is List<A>) LabelA.Text = _listA.Count;
else if(list is List<B>) LabelB.Text = _listB.Count;
else if(list is List<C>) LabelC.Text = _listC.Count;
// and so on...
else if(list is List<Z>) LabelZ.Text = _listZ.Count;
}
Overloading the function name doesn't reduce the number of lines of code:
private void setLabel(List<A> list)
{
LabelA.Text = _listA.Count;
}
private void setLabel(List<B> list)
{
LabelB.Text = _listB.Count;
}
I prefer to use the is operator to determine which Label to set, because it preserves space (in this scenario, 50 lines of meaningless brackets and 25 lines of slightly-different function names). However, a Stack Overflow user recommended that I not use generics, and instead use separate functions, one for each Label. Although this solution will work, I prefer to not do so.
Is there any benefit towards NOT using the is operator, and towards explicitly typing my functions?
The benefit is that your type checking is static, rather than dynamic. If someone passes in a List<SomeRandomeClassYouDontSupport> to the first method, then the code will compile and just not work properly at runtime. It'll either do nothing, throw an exception, or whatever you code it to do, but the point is that the caller won't be able to see that they did something wrong until they run the code.
When you have multiple overloads then the validation is done at compile time. If an unsupported type is provided then the code won't even compile rather than compiling and not working.
It's also an important semantic difference. Generics are there to say, "This method will work regardless of what the type is". When creating a list there are no right and wrong type arguments to provide. You can create a list of any type that you want. That's an appropriate use of generics, because lists are a conceptually generic data structure. Having several overloads is a way of saying, "This finite list of types is supported." You're in the latter case, so that makes that behavior clearer to the caller, so they'll understand what the method needs to do just by looking at its signature.
Having said all of that, it looks like this isn't even a situation where you should be doing either. If you really wanted to have a method accepting one of a finite number of types known at compile time as a parameter, overloads are the right way to do it, but in your case, you shouldn't be doing any of this at all. You should be binding these UI compontents to a view as mentioned in this comment.
Why not just make your own classes which derive their own fields automatically?
private class ListWithText : List<T>
{
int Text {
get { return this.Count; }
}
}
ListWithText<A> LabelA = new ListWithText<A>();
Console.WriteLine(LabelA.Text);
I will NOT comment about whether it is a good practice or not to do what you are doing :).
If the absence of a label for a given list is NOT the end of the world for you and if you rely on some naming conventions for your label fields so that all labels are named for example "LabelX" where X is your type that will be used for generic lists, you can do that:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace Labels
{
class Program
{
static void Main(string[] args)
{
Container c = new Container();
c.ApplyLabels();
}
}
public class A
{
}
public class B
{
}
public class C
{
}
public class Container
{
private Label LabelA = new Label ();
private Label LabelB = new Label ();
private Label LabelC = new Label ();
private List<A> _listA = new List<A> ();
private List<B> _listB = new List<B> ();
private List<C> _listC = new List<C> ();
public void ApplyLabels ()
{
var allFields = this.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
Dictionary<Type, FieldInfo> listFields = new Dictionary<Type, FieldInfo>();
Dictionary<Type, FieldInfo> labelMappings = new Dictionary<Type, FieldInfo>();
Dictionary<string, Type> namespacesForListGenericTypes = new Dictionary<string, Type>();
List<FieldInfo> possibleLabelFields = new List<FieldInfo>();
foreach (var field in allFields)
{
if (field.FieldType.IsGenericType)
{
var genericTypeDef = field.FieldType.GetGenericTypeDefinition();
if (genericTypeDef == typeof (List<>))
{
var genericArgument = field.FieldType.GetGenericArguments()[0];
listFields.Add(genericArgument, field); // remember list fields and for each list what generic type it has!
namespacesForListGenericTypes[genericArgument.Name] = genericArgument;
}
}
else if (typeof (Label).IsAssignableFrom (field.FieldType))
{
possibleLabelFields.Add(field);
}
}
foreach (var possible in possibleLabelFields)
{
if (possible.Name.Length < 6) continue;
var typeName = possible.Name.Substring(5);
Type genericListType;
if (namespacesForListGenericTypes.TryGetValue (typeName, out genericListType))
{
labelMappings[genericListType] = possible;
}
}
foreach (var list in listFields)
{
FieldInfo destination;
if (false == labelMappings.TryGetValue (list.Key, out destination))
{
continue;
}
var destinationLabel = destination.GetValue(this) as Label;
if (destinationLabel == null) continue;
var listValue = list.Value.GetValue(this) as IList;
var cnt = listValue == null ? 0 : listValue.Count;
destinationLabel.Text = cnt.ToString();
}
}
}
public class Label
{
public string Text { get; set; }
}
}

Using lambda for builder pattern

The telerik grid uses lambda syntax to enhance the builder patter when binding to columns.
.Columns(cols =>
{
cols.Bound(e => e.Tag);
cols.Bound(e => e.Name);
});
I would like to make a similar function in my code. I already have the syntax for the Bound() function down. But what would the syntax for the Columns() function look like?
Here is a better example of what I am trying to accomplish:
class SubList
{
private List<string> _items;
public AddItem(string item)
{
_items.Add(item);
}
}
class MyCollections
{
private Dictionary<string, SubList> _subs = new Dictionary<string,SublList>();
public SubList AddList(string name)
{
var newSub = new SubList();
_subs[name] = newSub;
return newSub;
}
}
class Other
{
public void DoStuff()
{
var collections = new MyCollections();
//if add item throws error, I don't know which one it is as.
//it is also hard to put a break point in here.
collections.AddList("one")
.AddItem("1")
.AddItem("un")
.AddItem("uno");
//I would like to have something like this:
collections.AddList("two") { s =>
s.AddItem("1");
s.AddItem("un"); //yay! can put breakpoint here
s.AddItem("uno");
};
//or perhaps
collections.AddList("two").Sub( s => {
s.AddItem("1");
s.AddItem("un"); //yay! can put breakpoint here
s.AddItem("uno");
});
}
}
It could either be an extension method or an instance method, probably on the order of:
// Assuming some grid type TDataGrid and some column building type TColumnBuilder
public TDataGrid Columns(Action<TColumnBuilder> applyColumns)
{
// Ask the user what they'd like to do with our columns
TColumnBuilder placeholder = new TColumnBuilder();
applyColumns(placeholder);
// do something with what we've learned
// this.columns = placeholder.CreateColumns();
}

Categories

Resources