我可以在WPF / XAML中获得强类型绑定吗?

时间:2021-05-17 04:14:46

Using the MVVM-pattern you set the DataContext to a specific ViewModel. Now is there any way to tell the XAML the type of the DataContext so that it will validate my bindings?

使用MVVM模式将DataContext设置为特定的ViewModel。现在有没有办法告诉XAML DataContext的类型,以便它将验证我的绑定?

Looking for something like the typed viewdata in ASP.NET MVC.

在ASP.NET MVC中寻找类似于viewdata的东西。

5 个解决方案

#1


3  

No, the current spec does not have strong typing in Xaml. I believe that with .Net 4.0, Xaml should be seeing the capacity for generics. With that, I would think it should be much easier to have strong typing in Xaml.

不,目前的规格在Xaml中没有强力输入。我相信,使用.Net 4.0,Xaml应该会看到泛型的容量。有了这个,我认为在Xaml中进行强大的输入应该会容易得多。

#2


3  

You can write each individual binding in a strongly-typed way:

您可以以强类型方式编写每个单独的绑定:

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

However this would not validate the fact that TextBox DataContext is of type ViewModel.Site (and I think this is not possible, but I may be wrong).

但是,这不会验证TextBox DataContext是ViewModel.Site类型的事实(我认为这是不可能的,但我可能是错的)。

#3


2  

No. FrameworkElement.DatatContext is the dependency property that enables data binding is of type object.

No. FrameworkElement.DatatContext是依赖项属性,它使数据绑定的类型为object。

As pointed out by others, you can specify the expected type of a DataContext for a special template called a DataTemplate. Many controls such as ItemsControl, ControlControl provide access to DataTemplates to allow you to set the visual representation's expectations of the DataContext's type.

正如其他人所指出的,您可以为名为DataTemplate的特殊模板指定DataContext的预期类型。许多控件(如ItemsControl,ControlControl)提供对DataTemplates的访问,以允许您设置可视化表示对DataContext类型的期望。

Bryan is correct, he did not test his code.

布莱恩是对的,他没有测试他的代码。

The correct application of a typed DataTemplate looks like this:

类型化DataTemplate的正确应用如下所示:

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

ContentPresenter inherits directly from FrameworkElement and does not have a Template property. In addition, the Template property commonly refers to Control.Template of type ControlTemplate which is something entirely different than a DataTemplate.

ContentPresenter直接从FrameworkElement继承,并且没有Template属性。此外,Template属性通常是指ControlTemplate类型的Control.Template,它与DataTemplate完全不同。

I think Bryan was thinking of the ContentControl which is one of the two root control types (the other being ItemsControl). ContentControl does in fact inherit from Control. Therefore we can specify the Template property on it if we so choose.

我认为Bryan正在考虑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


1  

I personally declare a static PropertyPath for each property in my viewmodel the reference this using x:static as the binding path - e.g

我个人为我的viewmodel中的每个属性声明一个静态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}}

xaml:{绑定路径= {x:静态本地:MyViewModel.MyPropertyPath}}

This way all my bindings get validated on build.

这样我的所有绑定都会在构建时得到验证。

#5


0  

Try this:

尝试这个:

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

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

I haven't tested this code but it should give you the idea. The content presenter will display the current DataContext which will use the DataTemplate. This isn't strongly typed in the compiler but will throw a runtime error immediately on load (in the window's InitializeComponent). You should be able to catch this easily in your testing if something breaks.

我没有测试过这段代码,但它应该给你一个想法。内容呈现器将显示将使用DataTemplate的当前DataContext。这在编译器中没有强类型,但会在加载时立即抛出运行时错误(在窗口的InitializeComponent中)。如果出现问题,您应该能够在测试中轻松捕捉到这一点。

#1


3  

No, the current spec does not have strong typing in Xaml. I believe that with .Net 4.0, Xaml should be seeing the capacity for generics. With that, I would think it should be much easier to have strong typing in Xaml.

不,目前的规格在Xaml中没有强力输入。我相信,使用.Net 4.0,Xaml应该会看到泛型的容量。有了这个,我认为在Xaml中进行强大的输入应该会容易得多。

#2


3  

You can write each individual binding in a strongly-typed way:

您可以以强类型方式编写每个单独的绑定:

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

However this would not validate the fact that TextBox DataContext is of type ViewModel.Site (and I think this is not possible, but I may be wrong).

但是,这不会验证TextBox DataContext是ViewModel.Site类型的事实(我认为这是不可能的,但我可能是错的)。

#3


2  

No. FrameworkElement.DatatContext is the dependency property that enables data binding is of type object.

No. FrameworkElement.DatatContext是依赖项属性,它使数据绑定的类型为object。

As pointed out by others, you can specify the expected type of a DataContext for a special template called a DataTemplate. Many controls such as ItemsControl, ControlControl provide access to DataTemplates to allow you to set the visual representation's expectations of the DataContext's type.

正如其他人所指出的,您可以为名为DataTemplate的特殊模板指定DataContext的预期类型。许多控件(如ItemsControl,ControlControl)提供对DataTemplates的访问,以允许您设置可视化表示对DataContext类型的期望。

Bryan is correct, he did not test his code.

布莱恩是对的,他没有测试他的代码。

The correct application of a typed DataTemplate looks like this:

类型化DataTemplate的正确应用如下所示:

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

ContentPresenter inherits directly from FrameworkElement and does not have a Template property. In addition, the Template property commonly refers to Control.Template of type ControlTemplate which is something entirely different than a DataTemplate.

ContentPresenter直接从FrameworkElement继承,并且没有Template属性。此外,Template属性通常是指ControlTemplate类型的Control.Template,它与DataTemplate完全不同。

I think Bryan was thinking of the ContentControl which is one of the two root control types (the other being ItemsControl). ContentControl does in fact inherit from Control. Therefore we can specify the Template property on it if we so choose.

我认为Bryan正在考虑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


1  

I personally declare a static PropertyPath for each property in my viewmodel the reference this using x:static as the binding path - e.g

我个人为我的viewmodel中的每个属性声明一个静态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}}

xaml:{绑定路径= {x:静态本地:MyViewModel.MyPropertyPath}}

This way all my bindings get validated on build.

这样我的所有绑定都会在构建时得到验证。

#5


0  

Try this:

尝试这个:

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

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

I haven't tested this code but it should give you the idea. The content presenter will display the current DataContext which will use the DataTemplate. This isn't strongly typed in the compiler but will throw a runtime error immediately on load (in the window's InitializeComponent). You should be able to catch this easily in your testing if something breaks.

我没有测试过这段代码,但它应该给你一个想法。内容呈现器将显示将使用DataTemplate的当前DataContext。这在编译器中没有强类型,但会在加载时立即抛出运行时错误(在窗口的InitializeComponent中)。如果出现问题,您应该能够在测试中轻松捕捉到这一点。