简体   繁体   中英

UWP Community Toolkit MasterDetailsView not binding as expected

I've been trying to implement the MasterDetailsView from the UWP Community Toolkit, with very little success. I mirrored the SampleApp source code with my own classes, and could not get the List I was using to display in either the Master or the Details panes. Finally, I tried creating a new project in VS, and copying the source code listed in the SampleApp exactly, using the same Email class as the Sample App uses. Despite copying everything perfectly, I get the same results.

I noticed several binding errors (shown below) in the Output window of VS which point to this being a binding issue, but as far as I can see I've followed the normal binding format that I've used on other applications and with other controls.

Error example:

Error: BindingExpression path error: 'Emails' property not found on 'MasterDetailsTest.MainPage'. BindingExpression: Path='Emails' DataItem='MasterDetailsTest.MainPage'; target element is 'Microsoft.Toolkit.Uwp.UI.Controls.MasterDetailsView' (Name='null'); target property is 'ItemsSource' (type 'Object')

There is at least one other question with this same issue on StackOverflow (I thought I had seen more), but no accepted answers, and none of the unaccepted answers solved the issue for me. I also tried checking the Toolkit Sample App source code on github, to see if there was missing source code listed in the SampleApp, but everything there is identical.

I'm pasting my source code below, can somebody please help to determine what's going wrong with this?

Previous Question (no accepted answers)

Master-Details view in UWP Community Toolkit

MainPage.xaml:

<Page
    x:Class="MasterDetailsTest.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:MasterDetailsTest"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <controls:MasterDetailsView BackButtonBehavior="Automatic" ItemsSource="{Binding Emails}" NoSelectionContent="Select an item to view" CompactModeThresholdWidth="720">
        <controls:MasterDetailsView.ItemTemplate>
            <DataTemplate>
                <StackPanel Margin="8,0">
                    <TextBlock Text="{Binding From}" Style="{ThemeResource SubtitleTextBlockStyle}" />
                    <TextBlock Text="{Binding Subject}" Style="{ThemeResource BodyTextBlockStyle}" Foreground="{ThemeResource Brush-Blue-01}" MaxLines="1" />
                    <TextBlock Text="{Binding Body}" Style="{ThemeResource BodyTextBlockStyle}" Opacity="0.6" MaxLines="1" />
                </StackPanel>
            </DataTemplate>
        </controls:MasterDetailsView.ItemTemplate>
        <controls:MasterDetailsView.DetailsTemplate>
            <DataTemplate>
                <RelativePanel Margin="24">
                    <controls:ImageEx x:Name="FromEllipse" Source="{Binding Thumbnail}" Width="50" Height="50" CornerRadius="999" />
                    <TextBlock Text="{Binding From}" Style="{ThemeResource SubtitleTextBlockStyle}" RelativePanel.RightOf="FromEllipse" Margin="12,-6,0,0" />
                    <TextBlock x:Name="SubjectLine" Text="{Binding Subject}" Style="{ThemeResource BodyTextBlockStyle}" RelativePanel.Below="FromEllipse" Margin="0,12,0,0" />
                    <TextBlock x:Name="Body" Text="{Binding Body}" Style="{ThemeResource BodyTextBlockStyle}" TextWrapping="Wrap" RelativePanel.Below="SubjectLine" Margin="0,12,0,0" />
                </RelativePanel>
            </DataTemplate>
        </controls:MasterDetailsView.DetailsTemplate>
        <controls:MasterDetailsView.NoSelectionContentTemplate>
            <DataTemplate>
                <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
                    <SymbolIcon Symbol="Mail" RenderTransformOrigin="0.5,0.5">
                        <SymbolIcon.RenderTransform>
                            <CompositeTransform ScaleX="2" ScaleY="2" />
                        </SymbolIcon.RenderTransform>
                    </SymbolIcon>
                    <TextBlock Text="{Binding}" FontSize="24" Margin="0,12" />
                </StackPanel>
            </DataTemplate>
        </controls:MasterDetailsView.NoSelectionContentTemplate>
        <controls:MasterDetailsView.MasterCommandBar>
            <CommandBar>
                <AppBarButton Icon="Back" Label="Back" />
                <AppBarButton Icon="Forward" Label="Forward" />
                <CommandBar.Content>
                    <TextBlock Margin="12,14">
                            <Run Text="{Binding Emails.Count}" />
                            <Run Text="Items" />
                    </TextBlock>
                </CommandBar.Content>
            </CommandBar>
        </controls:MasterDetailsView.MasterCommandBar>
        <controls:MasterDetailsView.DetailsCommandBar>
            <CommandBar>
                <AppBarButton Icon="MailReply" Label="Reply" />
                <AppBarButton Icon="MailReplyAll" Label="Reply All" />
                <AppBarButton Icon="MailForward" Label="Forward" />
            </CommandBar>
        </controls:MasterDetailsView.DetailsCommandBar>
    </controls:MasterDetailsView>
</Page>

MainPage.xaml.cs:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

namespace MasterDetailsTest
{
    public sealed partial class MainPage : Page
    {
        List<Email> Emails = new List<Email>
        {            
            new Email {From = "Steve Johnson", Subject = "Lunch Tomorrow", Body = "Are you available for lunch tomorrow? A client would like to discuss a project with you." },
            new Email { From = "Becky Davidson", Subject = "Kids game", Body = "Don't forget the kids have their soccer game this Friday. We have to supply end of game snacks." },
            new Email { From = "OneDrive", Subject = "Check out your event recap", Body = "Your new album.\r\nYou uploaded some photos to yuor OneDrive and automatically created an album for you." },
            new Email { From = "Twitter", Subject = "Follow randomPerson, APersonYouMightKnow", Body = "Here are some people we think you might like to follow:\r\n.@randomPerson\r\nAPersonYouMightKnow" },
        };

        public MainPage()
        {
            this.InitializeComponent();
            DataContext = this;
        }
    }
}

Email.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MasterDetailsTest
{
    public class Email
    {
        public string From { get; set; }
        public string Subject { get; set; }
        public string Body { get; set; }
        public Uri Thumbnail { get; set; }
    }    
}

This is not a binding issue, but a rendering issue.

During rendering, its unable to render because you are missing some critical content. But because we are using the Binding keyword instead of x:Bind , you will not get an error when you encounter a rendering error at runtime, but instead abort the rendering Email item, so we will see a blank.

The missing content is as follows:

  1. Brush: Brush-Blue-01
  2. Class field: Thumbnail

Brush-Blue-01 appears in MasterDetailsView.ItemTemplate , if you don't define this brush then you need to replace or delete it.

Thumbnail appears in MasterDetailsView.DetailsTemplate , it should be a property in the Email class, if you didn't define it, which would also cause an exception. So you can consider deleting the control that references this property, or perfect the definition of Email class.

Through discussion with Richard Zhang (above comments), I've discovered what the full issue with this was. There were actually two components to the issue, both interrelated to the other.

  1. The Community Toolkit SampleApp used {Binding} rather than {x:Bind} , which would have required setting the ItemsSource in the code file as well as in the XAML.
  2. In addition, the DataTemplate in XAML needed a {x:DataType} to be set as well.

Note: For {x:Bind} to work correctly, the ItemsSource (in this case List<Email> ) must be a global member; it must be declared within the class, but outside of any functions. It can be defined/manipulated within a function, but the initial declaration needs to be at class-level (I typically place them as the first thing in the class, immediately following the opening brackets).

I had tried each of these separately before posting the question, but not together at the same time. Once I made both of these changes (and to both DataTemplate sections), everything worked as expected.

For future reference, the correct XAML code is pasted below:

<controls:MasterDetailsView BackButtonBehavior="Automatic" ItemsSource="{x:Bind inbox}" NoSelectionContent="Select an item to view" CompactModeThresholdWidth="720">
    <controls:MasterDetailsView.ItemTemplate>
        <DataTemplate x:DataType="local:Email">
            <StackPanel Margin="8,0">
                <TextBlock Text="{x:Bind From}" Style="{ThemeResource SubtitleTextBlockStyle}" />
                <TextBlock Text="{x:Bind Subject}" Style="{ThemeResource BodyTextBlockStyle}" Foreground="{ThemeResource Brush-Blue-01}" MaxLines="1" />
                <TextBlock Text="{x:Bind Body}" Style="{ThemeResource BodyTextBlockStyle}" Opacity="0.6" MaxLines="1" />
            </StackPanel>
        </DataTemplate>
    </controls:MasterDetailsView.ItemTemplate>
    <controls:MasterDetailsView.DetailsTemplate>
        <DataTemplate x:DataType="local:Email">
            <RelativePanel Margin="24">
                <controls:ImageEx x:Name="FromEllipse" Source="{x:Bind Thumbnail}" Width="50" Height="50" CornerRadius="999" />
                <TextBlock Text="{x:Bind From}" Style="{ThemeResource SubtitleTextBlockStyle}" RelativePanel.RightOf="FromEllipse" Margin="12,-6,0,0" />
                <TextBlock x:Name="SubjectLine" Text="{x:Bind Subject}" Style="{ThemeResource BodyTextBlockStyle}" RelativePanel.Below="FromEllipse" Margin="0,12,0,0" />
                <TextBlock x:Name="Body" Text="{x:Bind Body}" Style="{ThemeResource BodyTextBlockStyle}" TextWrapping="Wrap" RelativePanel.Below="SubjectLine" Margin="0,12,0,0" />
            </RelativePanel>
        </DataTemplate>
    </controls:MasterDetailsView.DetailsTemplate>

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