Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Binding vs. x:Bind, using StaticResource as a default and their differences in DataContext

I've spent the better of half a day trying to make the ItemTemplate of a ListView with a UserControl configurable through means of a DependencyProperty on said UserControl. I've come across some weird inconsistencies regarding the two different Binding methods available on Windows 10 UAP platform ( Binding and x:Bind).

The UserControl looks like this and is part of a custom calendar component.

<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>

The EventItemTemplate is a DependencyProperty of the UserControl.

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));

Which is altered on one of the root pages to style the ListView in one way or the other, like so.

<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>

This is actually a working version, but I had to tinker around with it quite a bit. The first attempts were made by me with both x:Bind and Binding and without the DataContext on the RelativePanel as the UserControl is now. x:Bind would be functional when setting a value to EventItemTemplate in the root page, but it would not be able to use the default DataTemplate specified by the StaticResource when the root page did not specify anything. Binding on the other hand would use the default DataTemplate at all times, even when the the root page had a set an other value to EventItemTemplate.

By setting the DataContext on the RelativePanel to the UserControl Binding started worked like wanted it too. x:Bind still shows the same behavior.

Now I understand that Binding does not by default bind to the UserControl's DataContext, but I'm still not entirely sure why x:Bind doesn't work. Is this intended behavior or is there something wrong with my entire scheme here and is what I came up with just a lucky hack?

like image 952
Wesley Vrancken Avatar asked Sep 15 '15 09:09

Wesley Vrancken


1 Answers

From {x:Bind} markup extension:

The {x:Bind} markup extension—new for Windows 10—is an alternative to {Binding}. {x:Bind} lacks some of the features of {Binding}, but it runs in less time and less memory than {Binding} and supports better debugging.

At XAML load time, {x:Bind} is converted into what you can think of as a binding object, and this object gets a value from a property on a data source. The binding object can optionally be configured to observe changes in the value of the data source property and refresh itself based on those changes. It can also optionally be configured to push changes in its own value back to the source property. The binding objects created by {x:Bind} and {Binding} are largely functionally equivalent. But {x:Bind} executes special-purpose code, which it generates at compile-time, and {Binding} uses general-purpose runtime object inspection. Consequently, {x:Bind} bindings (often referred-to as compiled bindings) have great performance, provide compile-time validation of your binding expressions, and support debugging by enabling you to set breakpoints in the code files that are generated as the partial class for your page. These files can be found in your obj folder, with names like (for C#) .g.cs.

like image 78
Rahul Sonone Avatar answered Oct 15 '22 09:10

Rahul Sonone