I have a huge collection of objects of type Person, which I can not modify or inherit. This is person.cs
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
And I want to have additional Information in my Grid (Wpf Datagrid) which I have to lookup in a IValueConverter. But IValueConverters are a bad solution if you have a lot of Persons ( > 500 )
My idea was to create a wrapper like this:
public class PersonWrapper
{
public Person Content { get; set; }
public string GetAdditionalInfo
{
get { return Helper.GetMagicInfo(Content); }
}
}
With this trick I can avoid having a IValueConverter.
Now comes my question:
Can I implicitly (with MarkupExtension or with TypeConverter) "wrap" my class for use in Binding?
Edit: I wrote a TypeConverter and used a TemplateSelector. The TypeConverter:
public class PersonTypeConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context,
Type sourceType)
{
return sourceType == typeof(Person);
}
public override object ConvertFrom(ITypeDescriptorContext context,
System.Globalization.CultureInfo culture, object value)
{
var s = value as PersonWrapper;
if (s == null)
return new Person();
return s.Content;
}
public override bool CanConvertTo(ITypeDescriptorContext context,
Type destinationType)
{
return destinationType == typeof(string);
}
public override object ConvertTo(ITypeDescriptorContext context,
System.Globalization.CultureInfo culture, object value, Type destinationType)
{
return new PersonWrapper() {Content = value as Person};
}
}
And added the Attribute to Person.cs
[TypeConverter(typeof(PersonTypeConverter))]
And I used it like this:
<Window.Resources>
<DataTemplate x:Key="dt" DataType="{x:Type local:PersonWrapper}">
<StackPanel>
<Label Content="{Binding FirstName}" />
<Label Content="{Binding LastName}" />
</StackPanel>
</DataTemplate>
<local:CTemplateSelector DefaultTemplate="{StaticResource dt}" x:Key="CTemplateSelector" />
</Window.Resources>
<Grid>
<ContentControl Content="{Binding OurText}" ContentTemplateSelector="{StaticResource CTemplateSelector}" />
</Grid>
The TemplateSelector:
public class CTemplateSelector : DataTemplateSelector
{
/// <summary>When overridden in a derived class, returns a <see cref="T:System.Windows.DataTemplate" /> based on custom logic.</summary>
/// <returns>Returns a <see cref="T:System.Windows.DataTemplate" /> or null. The default value is null.</returns>
/// <param name="item">The data object for which to select the template.</param>
/// <param name="container">The data-bound object.</param>
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
Debug.WriteLine(item?.GetType());
return DefaultTemplate;
}
public DataTemplate DefaultTemplate
{
get ;
set ;
}
}
But the TemplateSelector always prints out Person as type.
答案 0 :(得分:1)
您应该能够从您的人物对象(例如
)中脱离public class MyPerson : Person
{
public string FirstLast
{ get { return string.Format( "{0} {1}", FirstName, LastName ); }}
public string LastFirst
{ get { return string.Format( "{0}, {1}", LastName, FirstName ); }}
public string YourOtherContext
{ get { return WhateverFunctionToGetContext( this ); }}
}
然后你有另一个函数返回你想要呈现的字符串。您的绑定获取人员结构的所有默认属性,并且您刚刚使用这些新属性进行了扩展而没有任何转换器。当网格绑定到它们时,它会像其他任何一个一样调用getter并返回该值。