InvalidCastException when remove item in ObservableCollection - wpf

I am doing a project using WPF and Prims.
When remove category in Categories, an error has occurred.
public ObservableCollection<CategoryModel> _categories;
public ObservableCollection<CategoryModel> Categories
{
get { return _categories; }
set
{
SetProperty(ref _categories, value);
}
}
public void OnNavigatedTo(NavigationContext navigationContext)
{
_journal = navigationContext.NavigationService.Journal;
var category = navigationContext.Parameters["categoryAdd"] as CategoryModel;
if (category != null)
Categories.Add(category);
category = navigationContext.Parameters["categoryDelete"] as CategoryModel;
if (category != null)
{
foreach(var elm in Categories)
if (elm.Id == category.Id)
Categories.Remove(elm); //⇒Error here
}
}
Error:
System.InvalidCastException: 'Cannot cast an object of type' System.Windows.Controls.SelectionChangedEventArgs' to type 'SaleManager.Wpf.Admin.Models.CategoryModel'. '
Why does this error occur? How to fix it?

You can't change a collection in a foreach while reading this collection.
you can do this:
var item = Categories.FirstOrDefault(elm=> elm.Id == category.Id);
Categories.Remove(item);

Use a for loop and iterate backwards. elm is supposed to be a CategoryModel:
if (category != null)
{
for (int i = Categories.Count - 1; i >= 0; --i)
{
CategoryModel elm = Categories[i];
if (elm.Id == category.Id)
{
Categories.Remove(elm);
}
}
}

Related

For Unity, How to loop to check if different objects are null, or in my case not in the gameobject i attach the script to

I have multiple Images in one script and an array of sprites in another. I assign each image a specific sprite if a specific controller is connected. Then attach the script to a game object and assign the needed images. I only have some images on each gameobject, If I don't have every image on the script I attach on the game object, it gives me errors about object not in scene.
So im still learning unity and C#, and this is what I have now, and it works. Just wondering if there's a cleaner way to do this null check with a loop, which kind of loop and how?
Thanks in advance!
public GameManager gameManager;
public UIMananger uIMananger;
public Image[] moveImg;
public Image RunImg;
public Image jumpImg;
public Image mainAttackImg;
public Image secondAttackImg;
public Image PauseImg;
public Image SelectImg;
public Image recenterCameraImg;
public Image showUiImg;
public Image chaosTestImg;
public Image firstPersonCameraImg;
public Image EnterImg;
public Image BackImg;
void Update()
{
if (gameManager.UsingXboxController)
{
XboxMap();
}
}
public void XboxMap()
{
if (moveImg[0] != null)
{
moveImg[0].sprite = uIMananger.controllerButtons[10];
}
if (moveImg[1] != null)
{
moveImg[1].sprite = uIMananger.controllerButtons[11];
}
if (moveImg[2] != null)
{
moveImg[2].sprite = uIMananger.controllerButtons[12];
}
if (moveImg[3] != null)
{
moveImg[3].sprite = uIMananger.controllerButtons[13];
}
if (RunImg != null)
{
RunImg.sprite = uIMananger.controllerButtons[3];
}
if (jumpImg != null)
{
jumpImg.sprite = uIMananger.controllerButtons[0]; ;
}
if (mainAttackImg != null)
{
mainAttackImg.sprite = uIMananger.controllerButtons[2];
}
if (secondAttackImg != null)
{
secondAttackImg.sprite = uIMananger.controllerButtons[1];
}
if (PauseImg != null)
{
PauseImg.sprite = uIMananger.controllerButtons[22];
}
if (SelectImg != null)
{
SelectImg.sprite = uIMananger.controllerButtons[23];
}
if (recenterCameraImg != null)
{
recenterCameraImg.sprite = uIMananger.controllerButtons[6];
}
if (showUiImg != null)
{
showUiImg.sprite = uIMananger.controllerButtons[5];
}
if (chaosTestImg != null)
{
chaosTestImg.sprite = uIMananger.controllerButtons[18];
}
if (firstPersonCameraImg != null)
{
firstPersonCameraImg.sprite = uIMananger.controllerButtons[8];
}
if (EnterImg != null)
{
EnterImg.sprite = uIMananger.controllerButtons[0];
}
if (BackImg != null)
{
BackImg.sprite = uIMananger.controllerButtons[1];
}
}

RSSService item with the same key multiple times

I have a RSSService with an item like the one show below
<item>
<title>Accessori per la cura della persona</title>
<link>http://www.myurl.it/accessori-per-la-cura-della-persona/</link>
<comments>http://www.myurl.it/accessori-per-la-cura-della-persona/#comments</comments>
<pubDate>Tue, 24 Oct 2017 09:29:44 +0000</pubDate>
<dc:creator><![CDATA[Farmacia Rizzo Davide]]></dc:creator>
<category><![CDATA[News]]></category>
<category><![CDATA[Offerte]]></category>
<category><![CDATA[Callifugo]]></category>
<category><![CDATA[Raspa piedi]]></category>
<category><![CDATA[Spazzola ceramica]]></category>
<category><![CDATA[Spazzola piatta]]></category>
<category><![CDATA[Spazzola tonda]]></category>
<category><![CDATA[Spazzole capelli]]></category>
<guid isPermaLink="false">http://www.myurl.it/?p=3982</guid>
<description>.....
To read all the content I use this:
List<Map> records;
...
records = rss.getResults();
...
for (Map m : records) {
Button b = new Button((String)m.get("title"));
if(((String)m.get("category")).equals(CATEGORY_OFFERTE)){
b.setIcon(iconStar);
} else {
b.setIcon(iconNews);
}
b.addActionListener((l)->{
Boolean can = Display.getInstance().canExecute((String)m.get("link"));
if(can != null && can) {
Display.getInstance().execute((String)m.get("link"));
} else {
ToastBar.Status status = ToastBar.getInstance().createStatus();
status.setMessage("Non riesco a connettermi");
status.setExpires(3000);
status.show();
}
});
recordsContainer.addComponent(b);
}
When I read the key "category" I always get the last entry (in this item "Spazzole capelli").
There is a way to read a key like an array? Something like that:
String[] mc = (String[]) m.get("category");
Thank's in advance for any help.
Davide.
This looks like a missing feature in RSSService that expects to find only one category entry and so it parses it into a hash map which effectively allows only one such entry.
I would suggest implementing your own RSS reading and go to the XML directly to get the full power of the protocol. You can use the existing class as a reference on how to do the RSS/ATOM parsing.
This is my idea
protected void textElement(String text) {
if(lastTag != null && current != null) {
// make "ATOM" seem like RSS
if("summary".equals(lastTag)) {
current.put("details", text);
} else {
if("content".equals(lastTag)) {
current.put("description", text);
} else {
if(current.get(lastTag) != null){
try {
List list = (List) current.get(lastTag);
list.add(text);
current.put(lastTag, list);
} catch (ClassCastException e){ // java.lang.String cannot be cast to java.util.List
List list = new ArrayList();
list.add((String)current.get(lastTag));
list.add(text);
current.put(lastTag, list);
}
} else {
current.put(lastTag, text);
}
}
}
}
}
Used in my Form like this:
for (Map m : records) {
Button b = new Button((String)m.get("title"));
try{
String category = (String)m.get("category");
if(category.equals(CATEGORY_OFFERTE)){
b.setIcon(iconStar);
} else {
b.setIcon(iconNews);
}
} catch (ClassCastException e){ // java.lang.String cannot be cast to java.util.List
b.setIcon(iconNews);
List list = (List) m.get("category");
for(int i=0; i < list.size(); i++){
if(((String)list.get(i)).equals(CATEGORY_OFFERTE)){
b.setIcon(iconStar);
}
}
}
b.addActionListener((l)->{
Boolean can = Display.getInstance().canExecute((String)m.get("link"));
if(can != null && can) {
Display.getInstance().execute((String)m.get("link"));
} else {
ToastBar.Status status = ToastBar.getInstance().createStatus();
status.setMessage("Non riesco a connettermi");
status.setExpires(3000);
status.show();
}
});
recordsContainer.addComponent(b);
}

Silverlight4 deep copy visual element

I have a custom visual element and i want to make a deep copy in my silverlight application.
I've tried many things but i didn't find any solution...
Here the best solution that i found but the original DeviceControl and the copy are linked.
If i change a property of one of them, the second also changes. I want them to be independent!
Have you got an idea?
void CloneDevice()
{
DeviceControl control = this;
DeviceControl copy = CloneObject.DeepClone<DeviceControl>(control);
ExtensionMethods.DeepCopy(control, copy);
}
//[Obfuscation(Exclude = true)]
internal static class CloneObject
{
private static bool _firstTry = false;
private static List<FieldInfo> _attachedProperties = null;
// Extension for any class object
internal static TT DeepClone<TT>(this TT source, bool?cloneAttachedProperties = null)
{ // Jim McCurdy's DeepClone
if (cloneAttachedProperties == null)
cloneAttachedProperties = (source is DependencyObject);
// The first time this method is called, compute a list of all
// attached properties that exist in this XAP's assemblies
if (cloneAttachedProperties == true && _attachedProperties == null)
{
_attachedProperties = new List<FieldInfo>();
List<Assembly> assemblies = GetLoadedAssemblies();
foreach (Assembly assembly in assemblies)
GetAttachedProperties(_attachedProperties, assembly);
}
TT clone = CloneRecursive(source);
if (clone is FrameworkElement)
{
FrameworkElement cloneElement = (clone as FrameworkElement);
cloneElement.Arrange(new Rect(0, 0, cloneElement.ActualWidth, cloneElement.ActualHeight));
}
return clone;
}
private static TT CloneRecursive<TT>(TT source)
{
if (source == null || source.GetType().IsValueType)
return source;
// Common types that do not have parameterless constructors
if (source is string || source is Type || source is Uri || source is DependencyProperty)
return source;
TT clone = CloneCreate(source);
if (clone == null)
return source;
if (source is IList)
CloneList(source as IList, clone as IList);
//CloneProperties(source, clone);//ca plante si on prend les propriétées comme ca
return clone;
}
private static TT CloneCreate<TT>(TT source)
{
try
{
#if DEBUG_TRACE
string.Format("Clone create object Type={0}", SimpleType(source.GetType())).Trace();
#endif
Array sourceArray = (source as Array);
if (sourceArray == null)
return (TT)Activator.CreateInstance(source.GetType());
if (sourceArray.Rank == 1)
return (TT)(object)Array.CreateInstance(source.GetType().GetElementType(),
sourceArray.GetLength(0));
if (sourceArray.Rank == 2)
return (TT)(object)Array.CreateInstance(source.GetType().GetElementType(),
sourceArray.GetLength(0), sourceArray.GetLength(1));
}
catch (Exception ex)
{
if (ex.Message.Contains("No parameterless constructor"))
return default(TT);
//string.Format("Can't create object Type={0}", SimpleType(source.GetType())).Trace();
//ex.DebugOutput();
}
return default(TT);
}
private static void CloneProperties(object source, object clone)
{
// The binding flags indicate what properties we will clone
// Unfortunately, we cannot clone "internal" or "protected" properties
BindingFlags flags =
BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.Public;
if (source is DependencyObject)
{
DependencyObject sourcedp = source as DependencyObject;
DependencyObject clonedp = clone as DependencyObject;
// Clone attached properties
if (_attachedProperties != null && _attachedProperties.Count > 0)
foreach (FieldInfo field in _attachedProperties)
CloneDependencyProperty(sourcedp, clonedp, field, true);
// Clone dependency properties
FieldInfo[] fields = source.GetType().GetFields(flags | BindingFlags.Static);
foreach (FieldInfo field in fields)
CloneDependencyProperty(sourcedp, clonedp, field, false);
}
// Clone CLR properties
if (source is DeviceControl && _firstTry == false)
{
_firstTry = true;
PropertyInfo[] properties = source.GetType().GetProperties(flags);
foreach (PropertyInfo property in properties)
CloneProperty(source, clone, property);
}
}
private static void CloneDependencyProperty(DependencyObject sourceObject,
DependencyObject cloneObject, FieldInfo field, bool isAttached)
{
try
{
// Blacklisted properties that can't (or shouldn't) be set
if (field.Name == "NameProperty" && sourceObject is FrameworkElement) return;
DependencyProperty dp = field.GetValue(sourceObject) as DependencyProperty;
if (dp == null) // Event DependencyProperties will be null
return;
object sourceValue = null;
try
{
sourceValue = sourceObject.GetValue(dp);
}
catch (Exception)
{
}
if (sourceValue == null)
return;
// Don't set attached properties if we don't have to
if (isAttached)
{
Type sourceType = sourceValue.GetType();
if (sourceType.IsValueType && sourceValue.Equals(Activator.CreateInstance(sourceType)))
return;
}
#if DEBUG_TRACE
string.Format("Clone dependency property Name={0}, Value={2} for source Type={1}",
field.Name, SimpleType(sourceObject.GetType()), sourceValue).Trace();
#endif
// Blacklisted properties that can't (or don't need to be) cloned
bool doClone = true;
if (field.Name == "DataContextProperty") doClone = false;
//if (field.Name == "TargetPropertyProperty") doClone = false;
object cloneValue = (doClone ? CloneRecursive(sourceValue) : sourceValue);
cloneObject.SetValue(dp, cloneValue);
}
catch (Exception ex)
{
if (ex.Message.Contains("read-only"))
return;
if (ex.Message.Contains("read only"))
return;
if (ex.Message.Contains("does not fall within the expected range"))
return;
//string.Format("Can't clone dependency property Name={0}, for source Type={1}",
// field.Name, SimpleType(sourceObject.GetType())).Trace();
//ex.DebugOutput();
}
}
private static void CloneProperty(object source, object clone, PropertyInfo property)
{
try
{
if (!property.CanRead || !property.CanWrite || property.GetIndexParameters().Length != 0)
return;
// Blacklisted properties that can't (or shouldn't) be set
if (property.Name == "Name" && source is FrameworkElement) return;
if (property.Name == "InputScope" && source is TextBox) return; // Can't get
if (property.Name == "Watermark" && source is TextBox) return; // Can't get
if (property.Name == "Source" && source is ResourceDictionary) return; // Can't set
if (property.Name == "TargetType" && source is ControlTemplate) return; // Can't set
bool publicSetter = (source.GetType().GetMethod("set_" + property.Name) != null);
bool isList = (property.PropertyType.GetInterface("IList", true) != null);
if (!publicSetter && !isList)
return;
object sourceValue = property.GetValue(source, null);
if (sourceValue == null)
return;
if (!publicSetter && isList)
{
IList cloneList = property.GetValue(clone, null) as IList;
if (cloneList != null)
CloneList(sourceValue as IList, cloneList);
return;
}
#if DEBUG_TRACE
string.Format("Clone property Type={0}, Name={1}, Value={3} for source Type={2}",
SimpleType(property.PropertyType), property.Name, SimpleType(source.GetType()),
sourceValue).Trace();
#endif
// Blacklisted properties that can't (or don't need to be) cloned
bool doClone = true;
if (source is FrameworkElement && property.Name == "DataContext") doClone = false;
//if (property.Name == "TargetProperty") doClone = false;
object cloneValue = (doClone ? CloneRecursive(sourceValue) : sourceValue);
property.SetValue(clone, cloneValue, null); // possible MethodAccessException
}
catch (Exception ex)
{
//string.Format("Can't clone property Type={0}, Name={1}, for source Type={2}",
// SimpleType(property.PropertyType), property.Name, SimpleType(source.GetType())).Trace();
//ex.DebugOutput();
}
}
private static void CloneList(IList sourceList, IList cloneList)
{
try
{
IEnumerator sourceEnumerator = sourceList.GetEnumerator();
Array sourceArray = sourceList as Array;
Array cloneArray = cloneList as Array;
int dim0 = (sourceArray != null && sourceArray.Rank > 0 ? sourceArray.GetLowerBound(0) : 0);
int dim1 = (sourceArray != null && sourceArray.Rank > 1 ? sourceArray.GetLowerBound(1) : 0);
while (sourceEnumerator.MoveNext())
{
object sourceValue = sourceEnumerator.Current;
#if DEBUG_TRACE
string.Format("Clone IList item {0}", sourceValue).Trace();
#endif
object cloneValue = CloneRecursive(sourceValue);
if (sourceArray == null)
cloneList.Add(cloneValue);
else
if (sourceArray.Rank == 1)
cloneArray.SetValue(cloneValue, dim0++);
else
if (sourceArray.Rank == 2)
{
cloneArray.SetValue(cloneValue, dim0, dim1);
if (++dim1 > sourceArray.GetUpperBound(1))
{
dim1 = sourceArray.GetLowerBound(1);
if (++dim0 > sourceArray.GetUpperBound(0))
dim0 = sourceArray.GetLowerBound(0);
}
}
}
}
catch (Exception ex)
{
//string.Format("Can't clone IList item Type={0}", SimpleType(sourceList.GetType())).Trace();
//ex.DebugOutput();
}
}
private static string SimpleType(Type type)
{
string typeName = type.ToString();
int index = typeName.LastIndexOf('[');
if (index < 0)
return typeName.Substring(typeName.LastIndexOf('.') + 1);
string collectionName = typeName.Substring(index);
collectionName = collectionName.Substring(collectionName.LastIndexOf('.') + 1);
typeName = typeName.Substring(0, index);
typeName = typeName.Substring(typeName.LastIndexOf('.') + 1);
return typeName + '[' + collectionName;
}
private static List<Assembly> GetLoadedAssemblies()
{
List<Assembly> assemblies = new List<Assembly>();
foreach (AssemblyPart part in Deployment.Current.Parts)
{
StreamResourceInfo sri =
Application.GetResourceStream(new Uri(part.Source, UriKind.Relative));
if (sri == null)
continue;
Assembly assembly = new AssemblyPart().Load(sri.Stream);
if (assembly != null && !assemblies.Contains(assembly))
assemblies.Add(assembly);
}
// Additional assemblies that are not found when examining of Deployment.Current.Parts above
Type[] types =
{
typeof(System.Windows.Application), // System.Windows.dll,
#if INCLUDE_ASSEMBLIES_WITHOUT_ATTACHED_PROPERTIES
typeof(System.Action), // mscorlib.dll,
typeof(System.Uri), // System.dll,
typeof(System.Lazy<int>), // System.Core.dll,
typeof(System.Net.Cookie), // System.Net.dll,
typeof(System.Runtime.Serialization.StreamingContext), // System.Runtime.Serialization.dll,
typeof(System.ServiceModel.XmlSerializerFormatAttribute), // System.ServiceModel.dll,
typeof(System.Windows.Browser.BrowserInformation), // System.Windows.Browser.dll,
typeof(System.Xml.ConformanceLevel), // System.Xml.dll,
#endif
};
foreach (Type type in types)
{
Assembly assembly = type.Assembly;
if (assembly != null && !assemblies.Contains(assembly))
assemblies.Add(assembly);
}
return assemblies;
}
private static bool GetAttachedProperties(List<FieldInfo> attachedProperties, Assembly assembly)
{
BindingFlags flags = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Static;
foreach (Type type in assembly.GetTypes())
{
FieldInfo[] fields = type.GetFields(flags);
MethodInfo[] methods = null;
foreach (FieldInfo field in fields)
{
if (field.FieldType==(typeof(DependencyProperty)))
continue;
if (!field.Name.EndsWith("Property"))
continue;
string fieldName = field.Name.Replace("Property", "");
string getName = "Get" + fieldName;
string setName = "Set" + fieldName;
bool foundGet = false;
bool foundSet = false;
if (methods == null)
methods = type.GetMethods(flags);
foreach (MethodInfo method in methods)
{
if (method.Name == getName && method.GetParameters().Length == 1 &&
method.GetParameters()[0].ParameterType== (typeof(DependencyObject)))
foundGet = true;
else
if (method.Name == setName && method.GetParameters().Length == 2 &&
method.GetParameters()[0].ParameterType==(typeof(DependencyObject)))
foundSet = true;
if (foundGet && foundSet)
break;
}
if (!(foundGet && foundSet))
continue;
try
{
DependencyProperty dp = field.GetValue(null) as DependencyProperty;
}
catch (Exception)
{
continue;
}
// Found an attached Dependency Property
attachedProperties.Add(field);
}
}
return true;
}
}
public static void DeepCopy(object source, object destination)
{
// Get properties
var propertyInfos = source.GetType().GetProperties();
// Evaluate
if (propertyInfos.Length > 0)
{
foreach (var propInfo in propertyInfos)
{
// Process only public properties
if (propInfo.CanWrite)
{
if (propInfo.Name == "IsSelected")
{
break;
}
else
{
object value = propInfo.GetValue(source, null);
propInfo.SetValue(destination, value, null);
// Evaluate
if (value != null)
{
var newPropInfo = value.GetType().GetProperties();
if (newPropInfo.Length > 0)
{
// Copy properties for each child where necessary
DeepCopy(
source.GetType().GetProperty(propInfo.Name),
destination.GetType().GetProperty(propInfo.Name));
}
}
}
}
}
}
}
I solved my issue. I finally used JSon.net library
void CloneDevice()
{
DeviceControl control = this;
string json = JsonConvert.SerializeObject(control, Formatting.Indented);
DeviceControl copy = (DeviceControl)JsonConvert.DeserializeObject(json, this.GetType());
}
Thanks to Olivier Dahan!

Context Menu on a Group Row in RadGridView

I found one old solution Here.
But GridViewExpander is obsolete in 2009. Proof Here.
How can i implement it (Context Menu on a Group Row in RadGridView) in another way?
No answers... =(
But i found solution.
The are two ways to solve it:
1) If you need custom style for your GridViewGroupRow - read about Templates Structure
2) If not, then just use somthing like this:
<TelerikNavigation:RadContextMenu.ContextMenu>
<TelerikNavigation:RadContextMenu Opened="RadContextMenuOpened" ItemClick="ContextMenuItemClick" x:Name="contextMenu">
</TelerikNavigation:RadContextMenu>
private void RadContextMenuOpened(object sender, RoutedEventArgs e)
{
var menu = (RadContextMenu)sender;
if (menu == null)
return;
var cell = menu.GetClickedElement<GridViewCell>();
var row = menu.GetClickedElement<GridViewRow>();
var groupRow = menu.GetClickedElement<GridViewGroupRow>();
if (cell != null && row != null)
{
if (!cell.DataColumn.IsFrozen)
{
//Code for current cell
}
}
if (groupRow != null)
{
//Code for groupRow
}
}
private void ContextMenuItemClick(object sender, RadRoutedEventArgs e)
{
if (_currentCell != null)
{
//Code for current cell
}
if (_currentGroupRow != null)
{
var menu = (RadContextMenu)sender;
var clickedItem = e.OriginalSource as RadMenuItem;
if (clickedItem != null)
{
foreach (var gridViewRow in _currentGroupRow.ChildrenOfType<GridViewRow>())
{
foreach (var gridViewCellBase in gridViewRow.Cells)
{
if (gridViewCellBase.Column.UniqueName == "PlanObject")
{
var val = gridViewCellBase.DataContext as YourObjectName;
if (val != null)
{
//.....
}
}
}
}
//....
}
}
}

WPF ICollectionView Filtering

I've written a code for filtering items in ComboBox:
My question is, how would you do that?
I think that this solution with reflection could be very slow..
ICollectionView view = CollectionViewSource.GetDefaultView(newValue);
view.Filter += this.FilterPredicate;
private bool FilterPredicate(object value)
{
if (value == null)
return false;
if (String.IsNullOrEmpty(SearchedText))
return true;
int index = value.ToString().IndexOf(
SearchedText,
0,
StringComparison.InvariantCultureIgnoreCase);
if ( index > -1) return true;
return FindInProperties(new string[] { "Property1", "Property2" }, value, SearchedText);
}
private bool FindInProperties(string[] properties, object value, string txtToFind)
{
PropertyInfo info = null;
for (int i = 0; i < properties.Length; i++)
{
info = value.GetType().GetProperty(properties[i]);
if (info == null) continue;
object s = info.GetValue(value, null);
if (s == null) continue;
int index = s.ToString().IndexOf(
txtToFind,
0,
StringComparison.InvariantCultureIgnoreCase);
if (index > -1) return true;
}
return false;
}
Why not just this:
ICollectionView view = CollectionViewSource.GetDefaultView(newValue);
IEqualityComparer<String> comparer = StringComparer.InvariantCultureIgnoreCase;
view.Filter = o => {
Person p = o as Person;
return p.FirstName.Contains(SearchedText, comparer)
|| p.LastName.Contains(SearchedText, comparer);
}
Do you need to search properties dynamically?

Resources