Обязательное поведение WPF, отличающееся, когда связанное свойство объявляется как интерфейс по сравнению с типом класса?

Это запустилось со странного поведения, что я думал, был связан с моей реализацией ToString(), и я задал этот вопрос: Почему не будет привязки данных WPF показывать текст, когда ToString () будет иметь сотрудничающий объект?

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

Когда я связываю Label.Content к свойству DataContext это объявляется как интерфейсный тип, ToString() назван на объекте периода выполнения, и маркировка отображает результат.

Когда я связываю TextBlock.Text к тому же свойству, ToString() никогда не называется и ничто не отображено. Но, если я изменяю заявленное свойство на конкретную реализацию интерфейса, оно работает как ожидалось.

Это так или иначе дизайном? Если так, какая-либо идея, почему?

Воспроизвести:

  • Создайте новое Приложение WPF (.NET 3,5 SP1)
  • Добавьте следующие классы:
public interface IFoo
{
    string foo_part1 { get; set; }
    string foo_part2 { get; set; }
}

public class Foo : IFoo
{
    public string foo_part1 { get; set; }

    public string foo_part2 { get; set; }

    public override string ToString() 
    { 
        return foo_part1 + " - " + foo_part2; 
    }
}
public class Bar
{
    public IFoo foo 
    { 
        get { return new Foo {foo_part1 = "first", foo_part2 = "second"}; } 
    }
}
  • Установите XAML Window1 к:

    
         
            
    
    
  • в Window1.xaml.cs:

public partial class Window1 : Window  
{  
    public Window1()  
    {  
        InitializeComponent();  
        DataContext = new Bar();  
    }  
}

При запуске этого приложения Вы будете видеть текст только однажды (наверху в маркировке). Если Вы изменяете тип foo свойство на Bar класс к Foo (вместо IFoo) и запущенный приложение снова, Вы будете видеть текст в обоих средствах управления.

8
задан Community 23 May 2017 в 11:45
поделиться

1 ответ

Да, вы правы. Очевидно, свойство ContentControl.Content реализовано иначе, чем свойство TextBlock.Text . Одно очевидное отличие, конечно же, заключается в том, что ContentControl фактически генерирует экземпляр TextBlock для объекта содержимого, который не является Visual и не имеет ] DataTemplate . TextBlock - нет. Он сам отобразит текст. В обоих случаях строка определяется

  1. IValueConverter (если присутствует в привязке)
  2. TypeConverter (если объявлен)
  3. объектом.ToString ()

Похоже, что этот алгоритм отличается только на шаге 3 между TextBlock и ContentControl , как вы показали. В то время как ContentControl фактически разрешает объект, стоящий за интерфейсом, TextBlock - нет. Интересно.

Думаю, тебе придется с этим жить. Теперь у вас есть несколько вариантов:

  • Раскрыть строковое свойство в вашем интерфейсе и привязать к нему
  • Раскрыть объект данных как конкретный класс вместо интерфейса
  • Использовать ContentControl вместо TextBlock
  • предоставляет IValueConverter и использует его в привязке
  • предоставляет TypeConverter для вашего интерфейса
  • делает что-то еще (возможно, есть еще)
3
ответ дан 5 December 2019 в 15:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: