在 UWP 中更改 属性 后视图未更新

View not updating after property change in UWP

我正在尝试显示通过 API 调用获得的一些数据。 但是数据没有显示在应用程序中。 我正在使用 INotifyPropertyChanged 接口。

我的xaml.cs代码:

public sealed partial class TravelListDetail : Page, INotifyPropertyChanged
    {
        private TravelList _travelList;

        public TravelList TravelList
        {
            get { return _travelList; }
            set { Set(ref _travelList, value); }
        }

        HttpDataService http = new HttpDataService();
        public TravelListDetail()
        {
            this.InitializeComponent();
        }

        protected override async void OnNavigatedTo(NavigationEventArgs e)
        {
            string s = "";
            var id = e.Parameter;

            Task task = Task.Run(async () =>
            {
                Windows.Storage.StorageFolder storageFolder = Windows.Storage.ApplicationData.Current.TemporaryFolder;
                Windows.Storage.StorageFile currentUser = await storageFolder.GetFileAsync("currentUser");
                s = await Windows.Storage.FileIO.ReadTextAsync(currentUser);
            });
            task.Wait(); // Wait

            base.OnNavigatedTo(e);

            var data = await http.GetAsync<TravelList>($"https://localhost:5001/api/TravelList/{id}", s);
            TravelList = data;
            TravelList.imageLocation = "../Assets/blank-aerial-beach-background-template_1308-28443.jpg";
        }

        protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
        {
            base.OnNavigatingFrom(e);
            if (e.NavigationMode == NavigationMode.Back)
            {
                NavigationService.Frame.SetListDataItemForNextConnectedAnimation(TravelList);
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void Set<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
        {
            if (Equals(storage, value))
            {
                return;
            }

            storage = value;
            OnPropertyChanged(propertyName);
        }

        private void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

    }

我的xaml代码:

<Page
    x:Class="TravelClient.Views.TravelListDetail"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:TravelClient.Views"
    xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
    xmlns:animations="using:Microsoft.Toolkit.Uwp.UI.Animations"
    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 x:Name="ContentArea">
        <ScrollViewer>
            <StackPanel>
                <RelativePanel>
                    <Grid
                        x:Name="Thumbnail"
                        Width="200"
                        Height="200"
                        Margin="{StaticResource SmallRightMargin}"
                        Padding="{StaticResource XSmallLeftTopRightBottomMargin}"
                        HorizontalAlignment="Left"
                        VerticalAlignment="Top"
                        Background="{ThemeResource SystemControlPageBackgroundChromeLowBrush}"
                        RelativePanel.AlignLeftWithPanel="True"
                        RelativePanel.AlignTopWithPanel="True">
                        <Image Source="{x:Bind TravelList.imageLocation}"></Image>
                    </Grid>
                </RelativePanel>
                <StackPanel>
                    <TextBlock Text="{x:Bind TravelList.Listname}"></TextBlock>
                    <TextBlock Text="test"></TextBlock>
                </StackPanel>
            </StackPanel>
        </ScrollViewer>
    </Grid>
</Page>

以下控件不会显示请求的数据。

<TextBlock Text="{x:Bind TravelList.Listname}"></TextBlock>

<Image Source="{x:Bind TravelList.imageLocation}"></Image>

API调用没有问题,数据设置到TravelList对象。

如果想在属性变化后更新控件,需要在TravelListclass中添加INotifyPropertyChanged接口通知class的属性变化=13=] class。您可以在 TravelListDetail 的泛型 Set() 方法处添加一个断点,并查看当 _travelList 的值发生变化时,不会触发泛型 Set() 方法。注意,{x:Bind}扩展的默认模式是OneTime,你需要使用OneWay 模式 {x:Bind} 扩展。

您可以查看以下代码:

.xaml.cs 代码:

public class TravelList: INotifyPropertyChanged
{
    private string imageLocation;
    public string ImageLocation
    {
        get { return imageLocation; }
        set
        {
            Set(ref imageLocation, value);
        }
    }
    private string listname;
    public string Listname {
        get { return listname; }
        set
        {
            Set(ref listname, value);
        }
    }

    private void Set<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
    {
        if (Equals(storage, value))
        {
            return;
        }

        storage = value;
        OnPropertyChanged(propertyName);
    }
    public TravelList()
    {
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    ......
}

.xaml 代码:

<Image Source="{x:Bind TravelList.ImageLocation,,Mode=OneWay}"></Image>
<TextBlock Text="{x:Bind TravelList.Listname,Mode=OneWay}"></TextBlock>

好吧,答案很简单。 我写的代码是正确的我只是忘了在 {x:Bind} 扩展中添加单向模式,就像@YanGu - MSFT 指出的那样。