Одно из моих самых больших домашних животных заставляет задуматься о том, как привязка данных к работе с XAML заключается в том, что нет возможности сильно набирать ваши данные. Другими словами, в С#, если вы хотите получить доступ к объекту на объекте, которого не существует, вы не получите никакой помощи от Intellisense, и если вы настаиваете на игнорировании Intellisense, компилятор схватит вас и выиграет ' я позволю вам продолжить - и я подозреваю, что многие люди здесь согласятся с тем, что это очень хорошая вещь. Но в привязке данных XAML вы работаете без сети. Вы можете привязываться ко всему, даже если он не существует. Действительно, учитывая странный синтаксис привязки данных XAML и, учитывая мой собственный опыт, гораздо сложнее связать с чем-то, что существует, чем с чем-то, что этого не происходит. У меня гораздо больше шансов, что мой синтаксис привязки данных неправильный, чем для правильной работы; и сравнительное время, которое я провожу для устранения неполадок с привязкой к базе данных XAML, легко затмевает время, которое я трачу с любой другой частью стека Microsoft (включая неудобный и раздражающий WCF, если вы можете в это поверить). И большинство из них (не все) восходит к тому, что без строго типизированных привязок данных я не могу получить никакой помощи ни от Intellisense, ни от компилятора.
Итак, что я хочу знать: почему MS не дает нам возможности иметь строго типизированные привязки данных: вроде как в VB6, мы могли бы сделать любой объект вариантом, если бы мы были действительно мазохистскими, но большую часть времени имело смысл использовать обычные типизированные переменные. Есть ли причина, почему MS не может этого сделать?
Вот пример того, что я имею в виду. В С#, если свойство "UsrID" не существует, вы получите предупреждение от Intellisense и ошибку от компилятора, если вы попробуете это:
string userID = myUser.UsrID;
Однако в XAML вы можете сделать все, что хотите:
<TextBlock Text="{Binding UsrID}" />
И ни Intellisense, ни компилятор, ни (самое удивительное) приложение во время выполнения не даст вам никакого намека на то, что вы сделали что-то не так. Теперь это упрощенный пример, но любое приложение реального мира, которое имеет дело со сложными графами объектов и сложным интерфейсом, будет иметь множество эквивалентных сценариев, которые не являются простыми и не являются простыми для устранения неполадок. И даже после того, как вы впервые сработали правильно, вы SOL, если вы реорганизуете свой код и измените свои имена свойств С#. Все будет скомпилировано, и оно будет работать без ошибок, но ничего не получится, оставив вас охотиться и проталкивать свой путь через все приложение, пытаясь выяснить, что сломалось.
Одно возможное предложение (с верхней части моей головы и которое я не продумал) могло бы быть примерно таким:
Для любой части логического дерева вы можете указать в XAML DataType объекта, который он ожидает, например:
<Grid x:Name="personGrid" BindingDataType="{x:Type collections:ObservableCollection x:TypeArgument={data:Person}}">
Это могло бы создать строго типизированный ObservableCollection <Person> Свойство TypedDataContext в файле .g.cs. Итак, в вашем коде:
// This would work
personGrid.TypedDataContext = new ObservableCollection<Person>();
// This would trigger a design-time and compile-time error
personGrid.TypedDataContext = new ObservableCollection<Order>();
И если вы получили доступ к этому TypedDataContext через элемент управления в сетке, он будет знать, к какому объекту вы пытались получить доступ.
<!-- It knows that individual items resolve to a data:Person -->
<ListBox ItemsSource="{TypedBinding}">
<ListBox.ItemTemplate>
<DataTemplate>
<!--This would work -->
<TextBlock Text="{TypedBinding Path=Address.City}" />
<!-- This would trigger a design-time warning and compile-time error, since it has the path wrong -->
<TextBlock Text="{TypedBinding Path=Person.Address.City} />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Я сделал запись в блоге здесь, которая объясняет больше о моих разочарованиях с привязкой данных WPF/XAML, и, я думаю, это будет значительно лучший подход. Есть ли причина, почему это не может работать? И кто-нибудь знает, планирует ли MS решить эту проблему (в соответствии с моим предложением или, надеюсь, лучше)?