Xamarin UWP 似乎绑定到错误的视图模型
Posted
技术标签:
【中文标题】Xamarin UWP 似乎绑定到错误的视图模型【英文标题】:Xamarin UWP seems to bind to the wrong view model 【发布时间】:2020-10-20 22:24:07 【问题描述】:我有一个适用于 android 和 UWP 的 Xamarin 项目。这个问题似乎只发生在 UWP 上。
在我的 Xamarin 项目中,我有 ContentPage
与绑定为上下文的视图模型。在这个 ViewModel 中有一个 ObservableCollection
和另一种视图模型。当我创建这个底层 ViewModel 的新实例并添加到我的 ObservableCollection 时,有时ContentPage
会按预期工作,在我的 ListView 中显示一个项目。但有时会添加一个空元素,将鼠标悬停在列表上时可以看到。发生这种情况时,我会在“输出”选项卡中收到一堆警告。
我的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?
【问题讨论】:
你能分享一下你是如何设置页面BindingContext
的吗?
@NicoZhu-MSFT - 我编辑包括如何将 DownloadsViewModel 设置为绑定上下文。
你的代码看起来是正确的,我们无法用上面的方法重现这个问题,你能不能用 onedrive 或 github 为我们分享一个代码示例?
@NicoZhu-MSFT 好的,我已经创建了一个清理项目,我可以在其中始终如一地重现它,但它现在似乎永远无法工作。我想在它工作之前是我在启动时加载已经创建的下载。当我在运行时创建下载时它不起作用。您可以在此处访问该项目:github.com/OrderlyFashion/Downloader
我已经下班了,明天可以检查一下吗?
【参考方案1】:
Xamarin UWP 似乎绑定到错误的视图模型
我检查了您的代码示例,它按预期工作。但是我发现进度值没有自动更新导致listview项无法显示,我已经更新了IDownload接口添加PercentDownloaded属性。对于测试,它可以在uwp平台上运行。
问题在于 ViewModel 没有为所有属性实现 INotifyPropertyChanged 的设置器。源代码在on Github,修复问题的提交是this one。
【讨论】:
如果您收到了上述项目,请告诉我们,为安全起见,我们需要及时删除。 我已经下载了代码,稍后再看。谢谢! 好的,请告诉我测试结果。 您的修复有效。谢谢!我不确定我是否完全理解问题所在。只需确保始终对 ViewModel 中的所有属性使用带有 INotifyPropertyChanged 的设置器?至少对我来说,错误消息肯定会让我感到困惑。 当然。我只是认为本着 *** 的精神,我们应该弄清楚实际的修复是什么。所以我已经将你的更改推送到 Github,我想我会离开这个项目。我会编辑你的答案以明确这一点。以上是关于Xamarin UWP 似乎绑定到错误的视图模型的主要内容,如果未能解决你的问题,请参考以下文章
错误 UWP 与 mvvmcross + xamarin 形式