1

I wanted to create an App to manage various Project, so i created a class to represent those Projects. In order to display them i created a user Control which should display then and later also manage the interaction between User and Project-Object. I tried to display a list of Projects in a Page but it does not work. I am not sure what to bind to in the Data Template, none of the ways i tried worked. I also used the live visual tree, and i think the Property Project of ProjectViewer is correctly set, but still the Textbook does not display the Name of the Project. (But I'm not so familiar with the live visual tree so i could be wrong). If i use the User Control as a single instance and not in a list i can set the Project property and the Name gets displayed. I think it is an issue with the DataBinding, but i couldn't work it out. Any help would be appreciated since this is only the very first step of the App and I'm already stuck.

Here is a minimal example i created to reproduce the problem:

I have a class Project:

using System.Collections.Generic;
using Windows.UI.Xaml;

namespace ProjectTimeTracker
{
    public class Project:DependencyObject
    {
        public string ProjName
        {
            get { return (string)GetValue(ProjNameProperty); }
            set { SetValue(ProjNameProperty, value); }
        }
        public static readonly DependencyProperty ProjNameProperty =
                DependencyProperty.Register(nameof(ProjName), typeof(string), typeof(Project), new PropertyMetadata("TestName"));

        public Project(){}
    }
}

And i created the UserControl ProjectViewer:

namespace ProjectTimeTracker.UI
{
    public sealed partial class ProjectViewer : UserControl
    {
        public Project Project
        {
            get { return (Project)GetValue(ProjectProperty); }
            set { SetValue(ProjectProperty, value); }
        }
        public static readonly DependencyProperty ProjectProperty =
                DependencyProperty.Register(nameof(Project), typeof(Project), typeof(ProjectViewer), new PropertyMetadata(null));


        public ProjectViewer()
        {
            this.InitializeComponent();
        }
    }
}

which has the following xaml code:

<UserControl
    x:Class="ProjectTimeTracker.UI.ProjectViewer"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:ProjectTimeTracker.UI"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="100"
    d:DesignWidth="400">

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="38"/>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="Auto"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <RadioButton x:Name="RBSelector" HorizontalAlignment="Left" Margin="8,0,0,0" VerticalAlignment="Center" Grid.RowSpan="2"/>
        <TextBlock x:Name="TBName" Grid.Row="0" Grid.Column="1" Text="{x:Bind Project.ProjName}" VerticalAlignment="Center" HorizontalAlignment="Left" Style="{ThemeResource TitleTextBlockStyle}" Width="110"/>
        <TextBlock x:Name="TBTotalTime" Grid.Row="1" Grid.Column="1" Text="NYI" HorizontalAlignment="Left" VerticalAlignment="Center" Style="{ThemeResource CaptionTextBlockStyle}" Margin="0,-4,0,0"/>

    </Grid>
</UserControl>

I try to use that User Control in the mainpage to create a list of Projects

using System.Collections.Generic;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

namespace ProjectTimeTracker
{
    public sealed partial class MainPage : Page
    {
        public List<Project> Projects
        {
            get { return (List<Project>)GetValue(ProjectsProperty); }
            set { SetValue(ProjectsProperty, value); }
        }
        public static readonly DependencyProperty ProjectsProperty =
                DependencyProperty.Register(nameof(Projects), typeof(List<Project>), typeof(MainPage), new PropertyMetadata(new List<Project>()));


        public MainPage()
        {
            this.InitializeComponent();

            Projects.Add(new Project() { ProjName="Projekt1"});
            list.ItemsSource = Projects;
        }
    }
}

The xaml looks like this:

<Page xmlns:UI="using:ProjectTimeTracker.UI" 
    x:Class="ProjectTimeTracker.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:ProjectTimeTracker"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <Grid>
        <ListView x:Name="list"  HorizontalAlignment="Center" VerticalAlignment="Center">
            <ListView.ItemTemplate>
                <DataTemplate x:DataType="local:Project">
                    <UI:ProjectViewer Project="{x:Bind }"/>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>
</Page>
2
  • You may not use x:Bind to Project property at all, subscribe to DataContextChanged and set Property in a callback, DataContext already has reference to your Project object. Use the already existing property for this purpose. Commented May 11, 2019 at 15:45
  • I deleted the Project="{x:Bind }" but now the app crashes when i add a project to the Projects List. This seems to be an issue with the Data Binding to ProjName in the ProjectViewer xaml. I get the following error: {Windows.UI.Xaml.UnhandledExceptionEventArgs} Exception: {System.NotImplementedException: The method or operation is not implemented. at ProjectTimeTracker.UI.ProjectViewer.ProjectViewer_obj1_Bindings.ProcessBindings(Object item, Int32 itemIndex, Int32 phase, Int32& nextPhase)} So far i did not even implement the DataContextChanged Handler Commented May 12, 2019 at 9:15

1 Answer 1

2

Use UserControl in ListViev UWP, Databinding Issue

I have modified your code, please refer the following,

ProjectViewer.xaml.cs

public sealed partial class ProjectViewer : UserControl
{
    public ProjectViewer()
    {
        this.InitializeComponent();
    }

    public Project ProjectSource
    {
        get { return (Project)GetValue(ProjectSourceProperty); }
        set { SetValue(ProjectSourceProperty, value); }
    }

    public static readonly DependencyProperty ProjectSourceProperty =
        DependencyProperty.Register("ProjectSource", typeof(Project), typeof(ProjectViewer), new PropertyMetadata(0, new PropertyChangedCallback(CallBack)));

    private static void CallBack(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var current = d as ProjectViewer;
        if (e.NewValue != e.OldValue)
        {
            current.TBName.Text = (e.NewValue as Project).ProjName;
        }
    }
}

public class Project
{
    public string ProjName { get; set; }

    public Project()
    {
    }
}

ProjectViewer.xaml

<RadioButton
    x:Name="RBSelector"
    Grid.RowSpan="2"
    Margin="8,0,0,0"
    HorizontalAlignment="Left"
    VerticalAlignment="Center"
    />
<TextBlock
    x:Name="TBName"
    Grid.Row="0"
    Grid.Column="1"
    Width="110"
    HorizontalAlignment="Left"
    VerticalAlignment="Center"
    Style="{ThemeResource TitleTextBlockStyle}"      
    />
<TextBlock
    x:Name="TBTotalTime"
    Grid.Row="1"
    Grid.Column="1"
    Margin="0,-4,0,0"
    HorizontalAlignment="Left"
    VerticalAlignment="Center"
    Style="{ThemeResource CaptionTextBlockStyle}"
    Text="NYI"
    />

Usage

public sealed partial class MainPage : Page
{
    public List<Project> Projects = new List<Project>();
    public MainPage()
    {
        this.InitializeComponent();     

        Projects.Add(new Project() { ProjName = "Projekt1" });       
        list.ItemsSource = Projects;
    }
    public string TestString { get; set; }
}

Xaml

<ListView
    x:Name="list"
    HorizontalAlignment="Center"
    VerticalAlignment="Center"
    >
    <ListView.ItemTemplate>
        <DataTemplate >
            <local:ProjectViewer ProjectSource="{Binding }" />
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks a lot, this works for me. I thought i can use the DataContextChanged Event to set my Property Project. But this works now. However im courios, because i had more Data Binding than just to ProjName (Just wanted to keep the example small). Can i not use Xaml DataBinding in my UserControl anymore and have to do it manually in the Callback? What feels a little bit odd to me is that my UserControl was working fine with Databinding when not used in a list. If there is a simple way to still use DataBinding? That would make the coding a little bit cleaner. (At least in my point of view)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.