2016-10-20 9 views
1

私はタイプの人物のオブジェクトの巨大なコレクションを持っています。これは私が変更または継承することはできません。 これはUIのラッパーに暗黙的にキャストすることはできますか?

public class Person 
{ 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
} 

person.csであると私はIValueConverterで検索する必要があり、私のグリッド(WPFデータグリッド)に追加情報を持っていると思います。私はIValueConverterを避けることができ、このトリックで

public class PersonWrapper 
{ 
    public Person Content { get; set; } 

    public string GetAdditionalInfo 
    { 
     get { return Helper.GetMagicInfo(Content); } 
    } 
} 

:あなたは私の考えは、このようにラッパーを作成することでした

者の多く(> 500)を持っている場合でも、IValueConvertersは悪いソリューションです。

は今私の質問に来る:

はI暗黙的に(MarkupExtensionを持つかのTypeConverterを持つ)の結合に使用するために私のクラスを "ラップ" することはできますか?


編集: 私はにTypeConverterを書き、TemplateSelectorを使用。 の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}; 
    } 
} 

そしてPerson.cs

[TypeConverter(typeof(PersonTypeConverter))] 

に属性を追加し、私はこのようにそれを使用:

<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> 

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 ; 
    } 
} 

しかしTemplateSelectorは常にPersonを型として出力します。

+1

2つの型の間で変更するために、ラッパーの2つの型の間に暗黙の演算子を追加します。 – Nkosi

+0

良い考えNkosiですが、この解決策でも、Personはラッパーで暗黙的に変換されません。 – Tobias

+1

コレクションはどのように入手していますか?暗黙的な演算子の考え方を使用すると、コレクションはラッパー・タイプになり、永続ストアから取り出されるときにそのアイテムが人になります。したがって、グリッドのデータソースはラッパー型で、人のクラスに渡されます – Nkosi

答えて

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); }} 
} 

としてあなたの個人オブジェクトからサブクラス化して逃げることができるはずです。あなたのバインディングは人構造のすべてのデフォルトプロパティを取得し、コンバーターなしでこれらの新しいプロパティで拡張したばかりです。グリッドがバインドされると、他のゲッターと同様にゲッターを呼び出し、その値を返します。

関連する問題