首页 > 解决方案 > 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));

    }

我的xml代码:

<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对象。

标签: c#data-bindinguwpinotifypropertychanged

解决方案


如果要在属性更改后更新控件,则需要INotifyPropertyChanged在类中添加接口以TravelList通知TravelList类属性的更改。Set()您可以在泛型方法处添加断点,TravelListDetail并查看当值_travelList更改时,Set()不会触发泛型方法。请注意, {x:Bind}扩展的默认模式是OneTime,您需要在{x:Bind}扩展中使用OneWay模式。

您可以检查以下代码:

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

推荐阅读