Search code examples
c#xamldata-bindingcode-behindwindows-runtime

Metro: Why is binding from XAML to a property defined in code-behind not working?


I am attempting to adapt a Windows Metro-style app sample slightly by binding the title text to a property defined in code-behind, but I can't seem to get it to work. Reading the blog post titled Bind from XAML to property defined in code-behind, I am trying out "Solution 1".

Here is my XAML source (simplified):

<UserControl x:Class="... .MainPage" x:Name="UserControlSelf"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="768" d:DesignWidth="1366">

    <Grid x:Name="LayoutRoot" Style="{StaticResource LayoutRootGridStyle}">
        <Grid.RowDefinitions>
            <RowDefinition Height="140"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <Grid x:Name="TitlePanel">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>

            <Button x:Name="BackButton" Click="BackButton_Click" Style="{StaticResource BackButtonStyle}"/>
            <TextBlock x:Name="PageTitle" Text="{Binding ElementName=UserControlSelf, Path=Title}" Style="{StaticResource TitleStyle}" Grid.Column="1"/>
        </Grid>
    </Grid>
</UserControl>

And here is my code-behind (simplified):

public partial class MainPage
{
    private string _title;

    public MainPage()
    {
        _title = "Test";
        InitializeComponent();
    }

    public string Title
    {
        get
        {
            return _title;
        }
    }

    //...
}

I set a breakpoint on the line return _title; in the getter of the Title property. When I debug the app, I see the back button, but the title text block control is blank (no text) and the breakpoint is not triggered:

Screenshot of the modified Metro-style app running, showing the back button, but no title

I set a breakpoint in the autogenerated C# code for the XAML file and verified that UserControlSelf is identical to this within InitializeComponent().

How do I bind the Text of the title text block control to the Title property defined in code-behind?


Solution

  • I was finally able to get it working. Instead of messing around with ElementName and Path, I simply set the MainPage instance's DataContext to an object other than the MainPage instance that had a Title property. I then changed the Text attribute of the title text block to {Binding Title}.

    It does not appear to be necessary for the data context object to implement Windows.UI.Xaml.Data.INotifyPropertyChanged; however, by doing so, the binding automatically behaves like a "one way" binding.

    I originally tried setting this.DataContext = this;, but, as I found out, that does not work. If I set it to a POCO or view model instance, then the binding is established.

    It would be interesting to know why this.DataContext = this; is erroneous, but at least I can now proceed.