WPF привязывает путь к имени типа класса

#wpf #data-binding #datatemplate

#wpf #привязка к данным #datatemplate

Вопрос:

Используя WPF, я хочу привязать заголовок GroupBox к имени типа полиморфного класса. Итак, если у меня есть класс с именем Element и два класса, производных от Element, такие как BasicElement и AdvancedElement, я хочу, чтобы в заголовке GroupBox было написано «BasicElement» или «AdvancedElement». Вот xaml, который я использую для GroupBox. Это часть DataTemplate, используемой ItemsControl. Я надеюсь на что-то вместо Path=DerivedTypeNameOf(group) в XAML, где group — это каждая группа в массиве groups.

Обратите внимание, что ObjectInstance для данных устанавливается в допустимый экземпляр GroupSet, который содержит массив некоторых базовых групп и расширенных групп.

Вот соответствующие классы, лежащие в основе кода:

 public class Group
{
    public string groupName;

    public string df_groupName
    {
        get { return this.groupName; }
        set { this.groupName = value; }
    }
}

public class BasicGroup : Group
{

}

public class AdvancedGroup : Group
{

}

public class GroupSet
{
    public Group [] groups;

    public Group [] df_groups
    {
        get { return this.groups; }
        set { this.groups = value; }
    }
};
  

Вот XAML:

 <UserControl.Resources>
    <ResourceDictionary>
        <ObjectDataProvider x:Key="TheData" />

        <DataTemplate x:Key="GroupTemplate">
            <GroupBox Header="{Binding Path=DerivedTypeNameOf(group)}">
                <TextBox Text="This is some text"/>
            </GroupBox>
        </DataTemplate>

    </ResourceDictionary>
</UserControl.Resources>

    <ItemsControl ItemsSource="{Binding Source={StaticResource TheData}, Path=groups}" ItemTemplate="{StaticResource GroupTemplate}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
    </ItemsControl>
  

Ответ №1:

Вы всегда можете использовать ValueConverter для получения типа:

 public class TypeNameConverter : IValueConverter {
  public object Convert(object value, Type targetType,
  object parameter, CultureInfo culture) {
    return value.GetType().Name;
  }

  public object ConvertBack(object value, Type targetType,
  object parameter, CultureInfo culture) {
    throw NotImplementedException();
  }
}
  

Это позволило бы вам иметь любой тип в вашей коллекции без какой-либо необходимости в реализации свойства для получения значения. В противном случае просто сделайте, как говорит Дэвид, и реализуйте свойство для получения результата. Вам даже не нужно было бы реализовывать это в каждом классе, если существует общее наследование от базового класса. Просто реализуйте это в базе с помощью GetType().Name, и вы всегда получите правильное значение.

Ответ №2:

Почему бы просто не добавить

 public abstract string DerivedTypeName { get; set; }
  

к вашему базовому классу и переопределяет его для каждого производного типа, тогда вы просто привязываетесь к строке.