绑定 vs x:Bind,在DataContext中使用StaticResource作为默认值的区别。

5
我花了半天时间尝试使用 DependencyProperty 使带有 UserControlListViewItemTemplate 可配置。在 Windows 10 UAP 平台上,我遇到了一些奇怪的不一致性,涉及两种不同的绑定方法(Bindingx:Bind)。

这个 UserControl 如下所示,并且是自定义日历组件的一部分。

<UserControl
   x:Class="FlowDesigner.UserControls.CalendarDayView"
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:local="using:FlowDesigner.UserControls"
   xmlns:vw="using:FlowDesigner.ViewModels"
   xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
   xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
   xmlns:uc="using:FlowDesigner.UserControls"
   mc:Ignorable="d"
   d:DesignHeight="300"
   d:DesignWidth="400"
   x:Name="DateControl">
   <UserControl.Resources>
      <DataTemplate x:Key="DefaultDataTemplate" x:DataType="vw:Event" >
          <uc:EventListTemplate IsToday="{Binding Date, Converter={StaticResource IsTodayConverter}}" 
                              Date="{Binding Date, Mode=OneWay}"
                              Summary="{Binding Path=Summary, Mode=OneWay}" />
      </DataTemplate>
   </UserControl.Resources>
   <RelativePanel Background="White" BorderBrush="Black" BorderThickness="1" DataContext="{Binding ElementName=DateControl}">
       <TextBlock x:Name="DayText" TextAlignment="Center" VerticalAlignment="Center" />
       <TextBlock x:Name="MonthText" TextAlignment="Center" VerticalAlignment="Center" RelativePanel.RightOf="DayText" />
       <ListView x:Name="EventList" ItemsSource="{x:Bind Events, Mode=OneWay}" 
              ItemTemplate="{Binding Path=EventItemTemplate, Mode=OneWay, FallbackValue={StaticResource DefaultDataTemplate}, TargetNullValue={StaticResource DefaultDataTemplate}}" 
              RelativePanel.Below="DayText" RelativePanel.AlignLeftWithPanel="True" RelativePanel.AlignRightWithPanel="True">

        </ListView>
    </RelativePanel>
</UserControl>
EventItemTemplateUserControl 的一个 DependencyProperty
public DataTemplate EventItemTemplate
{
    get { return (DataTemplate)GetValue(EventItemTemplateProperty); }
    set { SetValue(EventItemTemplateProperty, value); }
}

public static readonly DependencyProperty EventItemTemplateProperty =
        DependencyProperty.Register("EventItemTemplate", typeof(DataTemplate), typeof(CalendarDayView), new PropertyMetadata(null));

其中一个根页面上的内容被修改,以某种方式样式化ListView,就像这样。

<Style TargetType="uc:CalendarDayView">
    <Setter Property="EventItemTemplate">
        <Setter.Value>
            <DataTemplate x:DataType="vw:Event" >
                <TextBlock Text="{Binding Summary, Mode=OneWay}" />
            </DataTemplate>
        </Setter.Value>
    </Setter>
</Style>

这实际上是一个可用的版本,但我不得不对它进行一些调整。最初,我尝试了使用x:BindBinding,并且在RelativePanel上没有使用DataContext,就像现在的UserControl一样。当在根页面中为EventItemTemplate设置值时,x:Bind会正常工作,但当根页面没有指定任何内容时,它将无法使用由StaticResource指定的默认DataTemplate。另一方面,Binding始终会使用默认的DataTemplate,即使根页面已经为EventItemTemplate设置了其他值。
通过将RelativePanel上的DataContext设置为UserControlBinding可以按照预期工作。但x:Bind仍然显示相同的行为。
现在我明白了,默认情况下,Binding不会绑定到UserControlDataContext,但我仍然不完全确定为什么x:Bind不起作用。这是预期的行为还是我的整个方案存在问题,而我想出的只是一个幸运的hack?
1个回答

10

{x:Bind}标记扩展

{x:Bind}标记扩展是Windows 10中的一种替代{Binding}的方法。它缺少一些{Binding}的功能,但它执行的时间和内存占用比{Binding}更少,并且支持更好的调试。

在XAML加载时,{x:Bind}被转换为一个绑定对象,并从数据源的属性上获取值。绑定对象可选择配置以观察数据源属性值的变化并根据这些变化刷新自身。它也可以选择配置以将其自己的值的更改推回到源属性。由{x:Bind}和{Binding}创建的绑定对象在很大程度上具有相同的功能性。但{x:Bind}执行特殊目的的代码,在编译时生成,而{Binding}使用通用的运行时对象检查。因此,{x:Bind}绑定(通常称为已编译的绑定)具有良好的性能,通过启用您在代码文件中设置断点来支持调试,从而提供了绑定表达式的编译时验证。这些文件可以在obj文件夹中找到,文件名类似于(对于C#).g.cs。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接