简体   繁体   中英

Use UserControl in ListView UWP, Databinding Issue

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>

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>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM