首页 > 解决方案 > 在 ListView UWP 中使用 UserControl,数据绑定问题

问题描述

我想创建一个应用程序来管理各种项目,所以我创建了一个类来代表这些项目。为了显示它们,我创建了一个用户控件,该控件应在随后显示,然后还管理用户和项目对象之间的交互。我试图在页面中显示项目列表,但它不起作用。我不确定在数据模板中绑定什么,我尝试过的方法都没有。我还使用了实时可视化树,我认为 ProjectViewer 的属性项目设置正确,但教科书仍然没有显示项目名称。(但我对实时视觉树不太熟悉,所以我可能是错的)。如果我将用户控件用作单个实例而不是在列表中,我可以设置项目属性并显示名称。我认为这是 DataBinding 的问题,但我无法解决。

这是我为重现该问题而创建的一个最小示例:

我有一个班级项目:

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(){}
    }
}

我创建了 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();
        }
    }
}

它具有以下 xaml 代码:

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

我尝试在主页中使用该用户控件来创建项目列表

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

xaml 看起来像这样:

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

标签: c#xamllistviewdata-bindinguwp

解决方案


在 ListViev UWP 中使用 UserControl,数据绑定问题

我已经修改了您的代码,请参考以下内容,

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()
    {
    }
}

项目查看器.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"
    />

用法

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>

推荐阅读