Могу ли я получить строго типизированные привязки в WPF/XAML?

Используя MVVM -pattern, вы устанавливаете DataContext в определенную ViewModel. Теперь можно ли каким-либо образом указать XAML тип DataContext, чтобы он подтвердил мои привязки?

Ищете что-то вроде типизированных представлений в ASP.NET MVC.

Ответы

Ответ 1

Нет, текущая спецификация не имеет сильной печати в Xaml. Я считаю, что с .Net 4.0 Xaml должен видеть емкость для дженериков. С этим я бы подумал, что гораздо проще иметь сильную типизацию в Xaml.

Ответ 2

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

<TextBox Text="{Binding Path=(vm:Site.Contact).(vm:Contact.Name)}" />

Однако это не подтвердило бы тот факт, что TextBox DataContext имеет тип ViewModel.Site(и я думаю, что это невозможно, но я могу ошибаться).

Ответ 3

Нет. FrameworkElement.DatatContext - это свойство зависимостей, которое позволяет привязывать данные к типу object.

Как указывалось другими, вы можете указать ожидаемый тип DataContext для специального шаблона, называемого DataTemplate. Многие элементы управления, такие как ItemsControl, ControlControl, обеспечивают доступ к DataTemplates, чтобы вы могли установить ожидания визуального представления типа DataContext.

Брайан прав, он не проверял свой код.

Правильное применение типизированного DataTemplate выглядит следующим образом:

<Window>
    <Window.Resources>
        <DataTemplate x:Key="TypedTemplate" DataType="{x:Type myViewModel}">
        ...
        </DataTemplate>
    </Window.Resources>
    <ContentControl Content="{Binding}" ContentTemplate="{StaticResource TypedTemplate}" />
</Window>

ContentPresenter наследует напрямую от FrameworkElement и не имеет свойства Template. Кроме того, свойство Template обычно относится к Control.Template типа ControlTemplate, который является чем-то совершенно иным, чем DataTemplate.

Я думаю, что Брайан думал о ContentControl, который является одним из двух корневых типов управления (другое - ItemsControl). ContentControl действительно наследует Control. Поэтому мы можем указать свойство Template на нем, если мы это сделаем.

<Window>
   <Window.Resources>
      <DataTemplate x:Key="TypedTemplate" DataType="{x:Type myViewModel}">
      ...
      </DataTemplate>
      <ControlTemplate x:Key="ControlSkin" TargetType="{x:Type ContentControl}">
      ...
      </ControlTemplate>
   </Window.Resources>
   <ContentControl Content="{Binding}" ContentTemplate="{StaticResource TypedTemplate}" Template="{StaticResource ControlSkin}" />
</Window>

Ответ 4

Я лично объявляю статическую PropertyPath для каждого свойства в моей модели просмотра ссылкой, используя x: static как путь привязки - например

public class MyViewModel
{
  public static PropertyPath MyPropertyPath = new PropertyPath("MyProperty");
  public bool MyProperty{get; set;}
}

xaml: {Binding Path={x:Static local:MyViewModel.MyPropertyPath}}

Таким образом, все мои привязки проверяются при сборке.

Ответ 5

Попробуйте следующее:

<Window>
    <Window.Resources>
        <DataTemplate x:Key="TypedTemplate" DataType="{x:Type myViewModel}">
            ...
        </DataTemplate>
    </Window.Resources>

    <ContentPresenter Content="{Binding}" Template="{StaticResource TypedTemplate}" />
</Window>

Я не тестировал этот код, но он должен дать вам эту идею. Ведущий контента отобразит текущий DataContext, который будет использовать DataTemplate. Это не сильно типизировано в компиляторе, но сразу же выгрузит ошибку выполнения при загрузке (в окне InitializeComponent). Вы должны уметь легко поймать это в своем тестировании, если что-то сломается.