Search code examples
c#xamluwpwin-universal-appdependency-properties

UWP DependencyProperty Binding and DataTemplate Binding


I have a PlaylistControl (it is a UserControl) with a variable ShowAlbumText declared in this way:

    public bool ShowAlbumText
    {
        get => (bool)GetValue(ShowAlbumTextProperty);
        set => SetValue(ShowAlbumTextProperty, value);
    }
    public static readonly DependencyProperty ShowAlbumTextProperty = DependencyProperty.Register("ShowAlbumText", 
                        typeof(bool),
                        typeof(PlaylistControl),
                        new PropertyMetadata(true));

And ShowAlbumText is used in a ListView.ItemTemplate in the xaml of PlaylistControl this way:

<ListView>
    <ListView.ItemTemplate>
        <DataTemplate x:DataType="data:Music">
            <local:PlaylistControlItem DataContext="{x:Bind}" ShowAlbumText="{Binding ShowAlbumText}">
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

However, this Binding reports an error

Error: BindingExpression path error: 'ShowAlbumText' property not found on 'SMPlayer.Models.Music'. BindingExpression: Path='ShowAlbumText' DataItem='SMPlayer.Models.Music'; target element is 'SMPlayer.Controls.PlaylistControlItem' (Name='null'); target property is 'ShowAlbumText' (type 'Boolean')

So how I can bind the ShowAlbumText to the PlaylistControlItem? I understand that ShowAlbumText is NOT a property of Music (Music is my ViewModel). It is a DependencyProperty of my UserControl. A more general question, how can I bind both DependencyProperty from my UserControl and ViewModel from ItemsSource to a DataTemplate?

Source XAML.

Source Csharp Code.


Solution

  • You can use ElementName to make a binding point to a property of an element in your XAML instead of a property of the data context. In your case, you would want that element to be the UserControl/PlaylistControl.

    Give the UserControl element a Name:

    <UserControl x:Class="WhateverYourNamespaceIs.PlaylistControl"
        ...
        x:Name="Foo">
    

    Point your binding to the element with that name:

    <local:PlaylistControlItem DataContext="{x:Bind}" ShowAlbumText="{Binding ElementName=Foo, Path=ShowAlbumText}">