DataTemplate.DataType = Collection <Entity>?
Is there a way to create a data template that processes a list of items?
I have Contact.Phones ( EntityCollection<Phone> ) and I want the data template to process the list - add deletion, etc.
Is there a way to set the DataType property for a DataTemplate in a generic EntityCollection<Phone> ?
Wrap your public list in a new class that subclasses your public list without adding anything. This allows you to bind to a list from XAML. This is described here: Is it possible to specify a generic type in XAML (pre.NET 4 Framework)?
In my Emerald Data Foundation (EDF) tool, I solved this by creating a more powerful MarkupExtension than x: Type, which can also indicate generic types. So I could write:
<DataTemplate TargetType="{edf:Type generic:ICollection{local:Entity}}" /> Here is what I used:
[MarkupExtensionReturnType(typeof(Type))] public class TypeExtension : MarkupExtension { public TypeExtension() { } public TypeExtension(string typeName) { TypeName = typeName; } public TypeExtension(Type type) { Type = type; } public string TypeName { get; set; } public Type Type { get; set; } public override object ProvideValue(IServiceProvider serviceProvider) { if(Type==null) { IXamlTypeResolver typeResolver = serviceProvider.GetService(typeof(IXamlTypeResolver)) as IXamlTypeResolver; if(typeResolver==null) throw new InvalidOperationException("EDF Type markup extension used without XAML context"); if(TypeName==null) throw new InvalidOperationException("EDF Type markup extension used without Type or TypeName"); Type = ResolveGenericTypeName(TypeName, (name) => { Type result = typeResolver.Resolve(name); if(result==null) throw new Exception("EDF Type markup extension could not resolve type " + name); return result; }); } return Type; } public static Type ResolveGenericTypeName(string name, Func<string, Type> resolveSimpleName) { if(name.Contains('{')) name = name.Replace('{', '<').Replace('}', '>'); // Note: For convenience working with XAML, we allow {} instead of <> for generic type parameters if(name.Contains('<')) { var match = _genericTypeRegex.Match(name); if(match.Success) { Type[] typeArgs = ( from arg in match.Groups["typeArgs"].Value.SplitOutsideParenthesis(',') select ResolveGenericTypeName(arg, resolveSimpleName) ).ToArray(); string genericTypeName = match.Groups["genericTypeName"].Value + "`" + typeArgs.Length; Type genericType = resolveSimpleName(genericTypeName); if(genericType!=null && !typeArgs.Contains(null)) return genericType.MakeGenericType(typeArgs); } } return resolveSimpleName(name); } static Regex _genericTypeRegex = new Regex(@"^(?<genericTypeName>\w+)<(?<typeArgs>\w+(,\w+)*)>$"); } The generic type name parsing code is used in a separate method, since it is also used by other code in EDF. You could combine all this in one method.