繁体   English   中英

Xamarin UWP 似乎绑定到错误的视图 model

[英]Xamarin UWP seems to bind to the wrong view model

我有一个 Xamarin 项目,用于 Android 和 UWP。 这个问题似乎只发生在 UWP 上。

在我的 Xamarin 项目中,我将ContentPage与视图 model 绑定为上下文。 在这个 ViewModel 中有一个带有另一种视图 model 的ObservableCollection 当我创建这个底层 ViewModel 的新实例并添加到我的 ObservableCollection 时,有时ContentPage会按预期工作,在我的 ListView 中显示一个项目。 但有时会添加一个空元素,将鼠标悬停在列表上时可以看到。 发生这种情况时,我会在 Output 选项卡中收到一堆警告。

我的DownloadsPage

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:local="clr-namespace:Downloader.Converters"
             mc:Ignorable="d"
             x:Class="Downloader.Views.DownloadsPage">

    <ContentPage.Resources>
        <ResourceDictionary>
            <local:DownloadStatusToColorConverter x:Key="downloadStatusToColor" />
        </ResourceDictionary>
    </ContentPage.Resources>

    <RefreshView IsRefreshing="{Binding IsBusy, Mode=TwoWay}" Command="{Binding LoadItemsCommand}">
        <ListView x:Name="DownloadsListView" SelectionMode="None" ItemsSource="{Binding Downloads}" RowHeight="70">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <StackLayout Padding="10" BackgroundColor="{Binding DownloadStatus, Converter={StaticResource downloadStatusToColor}}">
                            <Label Text="{Binding Name}"
                                   d:Text="{Binding .}"
                                   LineBreakMode="NoWrap"
                                   Style="{DynamicResource ListItemTextStyle}"
                                   FontSize="16" />
                            <Grid Grid.Row="0" Grid.Column="0" Padding="10,0,10,0">
                                <ProgressBar BackgroundColor="Transparent"  Progress="{Binding PercentDownloaded}" HorizontalOptions="FillAndExpand" HeightRequest="20">
                                </ProgressBar>
                                <Label Text="{Binding PercentString}" HorizontalTextAlignment="Center"></Label>
                            </Grid>
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </RefreshView>

</ContentPage>

DownloadsViewModel在代码隐藏中设置为上下文,如下所示:

public partial class DownloadsPage : ContentPage
{
    private readonly DownloadsViewModel _viewModel;

    public DownloadsPage()
    {
        InitializeComponent();

        BindingContext = _viewModel = new DownloadsViewModel();

        Device.StartTimer(TimeSpan.FromSeconds(1), () =>
        {
            Device.BeginInvokeOnMainThread(() => _viewModel.RefreshDownloads());
            return true;
        });
    }
}

绑定的DownloadsViewModel

public class DownloadsViewModel : BaseViewModel
{
    public ObservableCollection<DownloadViewModel> Downloads { get; set; } = new ObservableCollection<DownloadViewModel>();
 
    public Command LoadItemsCommand { get; set; }

    public DownloadsViewModel()
    {
        Title = "Downloads";
        LoadItemsCommand = new Command(() => {
            IsBusy = true;
            Downloads.Clear();
            RefreshDownloads();
            IsBusy = false;
        });
    }

    public void RefreshDownloads()
    {
        foreach (var download in DownloadManager.GetDownloads())
        {
            var existingDownload = Downloads.FirstOrDefault(d => d.Id == download.Id);

            if (existingDownload != null)
            {
                existingDownload.UpdateValues(download);
            }
            else
            {
                Downloads.Add(new DownloadViewModel(download));
            }
        }
    }
}

ObservableCollection包含如下所示的DownloadViewModel

public class DownloadViewModel : BaseViewModel
{
    private IDownload _download;
    public DownloadViewModel(IDownload download)
    {
        UpdateValues(download);
    }

    private string _id;
    public string Id
    {
        get { return _id; }
        set { SetProperty(ref _id, value); }
    }

    private string _name;
    public string Name
    {
        get { return _name; }
        set { SetProperty(ref _name, value); }
    }

    private DownloadStatus _status;
    public DownloadStatus DownloadStatus
    {
        get { return _status; }
        set { SetProperty(ref _status, value); }
    }

    public double PercentDownloaded
    {
        get
        {
            return _download.DownloadedBytes == -1
                ? 0f
                : (double)_download.DownloadedBytes / _download.TotalBytes;
        }
    }

    public string PercentString { get => $"{(int)(PercentDownloaded * 100)} %"; }

    public void UpdateValues(IDownload download)
    {
        _download = download;
        Id = _download.Id;
        Name = _download.Name;
        DownloadStatus = _download.Status;
    }
}

我有时遇到的错误会导致我的 ListView 中的项目为空:

Binding: 'DownloadStatus' property not found on 'Downloader.ViewModels.DownloadsViewModel', target property: 'Xamarin.Forms.StackLayout.BackgroundColor'
Binding: 'Name' property not found on 'Downloader.ViewModels.DownloadsViewModel', target property: 'Xamarin.Forms.Label.Text'
Binding: 'PercentDownloaded' property not found on 'Downloader.ViewModels.DownloadsViewModel', target property: 'Xamarin.Forms.ProgressBar.Progress'
Binding: 'PercentString' property not found on 'Downloader.ViewModels.DownloadsViewModel', target property: 'Xamarin.Forms.Label.Text'

悬停时看到的幽灵物品

调试时,我已确认该项目已按预期添加到我的 ObservableCollection 中。

为什么有时它会在 DownloadsViewModel 而不是 DownloadViewModel 上寻找 DownloadStatus、Name、PercentDownloaded 和 PercentString?

Xamarin UWP 似乎绑定到错误的视图 model

我检查了您的代码示例,它按预期工作。 但是我发现进度值没有自动更新导致listview项无法显示,我已经更新了IDownload接口添加PercentDownloaded属性。 对于测试,它可以在 uwp 平台上工作。

问题是 ViewModel 没有为所有属性实现 INotifyPropertyChanged 的设置器。 源代码在 Github 上可用,修复问题的提交就是这个

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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