Binding vs. x:Bind,使用StaticResource作为默认值,它们在DataContext中的区别

本文关键字:DataContext 区别 默认值 vs Bind 使用 Binding StaticResource | 更新日期: 2023-09-27 18:12:43

我花了半天的时间试图通过UserControl上的DependencyProperty来配置ListViewItemTemplateUserControl。我遇到了一些奇怪的不一致关于两种不同的Binding方法在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>

EventItemTemplateUserControlDependencyProperty

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设置为UserControl, Binding也开始像想要的那样工作。x:Bind仍然显示相同的行为。

现在我明白,Binding不默认绑定到UserControlDataContext,但我仍然不完全确定为什么x:Bind不工作。这是有意为之的行为,还是我的整个计划出了什么问题,是我想出的只是一个幸运的黑客?

Binding vs. x:Bind,使用StaticResource作为默认值,它们在DataContext中的区别

From {x:Bind}标记扩展名:

{x:Bind}标记扩展- Windows 10的新功能-是{Binding}的替代方案。{x:Bind}缺少{Binding}的一些特性,但是它比{Binding}运行的时间和内存更少,并且支持更好的调试。

在XAML加载时,{x:Bind}被转换成您可以认为是绑定对象的东西,并且该对象从数据源上的属性获取值。绑定对象可以选择性地配置为观察数据源属性值的变化,并根据这些变化刷新自身。还可以选择将其配置为将其自身值中的更改推回源属性。{x:Bind}和{binding}创建的绑定对象在功能上基本上是相同的。但是{x:Bind}执行在编译时生成的特殊目的代码,而{Binding}使用通用的运行时对象检查。因此,{x:Bind}绑定(通常称为编译绑定)具有出色的性能,提供绑定表达式的编译时验证,并通过使您能够在作为页面的部分类生成的代码文件中设置断点来支持调试。这些文件可以在你的obj文件夹中找到,文件名如(c#) .g.cs.