這是我在Xamarin中對MVVM的第一次測驗。我試圖顯示一個由Web API提供的物件(例子)的串列,并將其記為ExampleList。它接收到了正確的資料和物件結構,api和app的模型幾乎是1:1。
當頁面加載時,它呈現了所有 9 個正確的元素,盡管這些元素的文本沒有顯示。我知道這些資料是正確的,因為當一個元素被點擊時,它會在一個顯示提示中顯示其物件的欄位。
我確定問題出在標記上,因為你可以看到下面它被宣告為。
"Severity Code Description Project File Line Suppression State
錯誤 XFC0045 系結。屬性"ID"在"App2.ViewModels.ExampleListViewModel"上未找到。App2 E:App2App2ViewsExampleListPage.xaml 22"。
就我的理解,它應該是假設和系結屬性物件的父物件是來自視圖模型的例子。
我還嘗試在 ViewModel 中手動宣告物件欄位,這確實可以編譯,但有類似的結果,即不顯示文本。
這個問題的奇怪之處在于,當應用程式正在運行時,文本單元的屬性宣告可以從 Object.Property 改為 Property,并將顯示文本,但在重新編譯時又會產生上述的相同錯誤。
xaml的代碼如下:
<?xml version="1.0" encoding="utf-8" ? >
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"/span>
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"。
x:Class="App2.Views.ExampleListPage"。
xmlns:viewmodels="clr-namespace:App2.ViewModels"/span>
x:DataType="viewmodels:ExampleListViewModel"。
Title="Example List">。
<ContentPage.BindingContext>
<viewmodels:ExampleListViewModel/>
</ContentPage.BindingContext>
<ListView x: Name="listView" Margin="20" SelectedItem="{Binding SelectedElement, Mode=TwoWay}" ItemsSource="{Binding ExampleList}"
RefreshCommand="{Binding RefreshCommand}"/span> IsRefreshing="{Binding IsBusy, Mode=OneWay}" IsPullToRefreshEnabled="True">
<ListView.ItemTemplate>
<DataTemplate>/span>
<TextCell Text="{binding ID}" Detail="{binding Example. Desc}"/>
</DataTemplate>/span>
</ListView.ItemTemplate>
</ListView>/span>
</ContentPage>
該頁后面的代碼如下:
using App2.ViewModels;
using System.Collections.Generic;
using System.Text.Document; using System.Text.Document
使用System.Threading.Tasks;
using Xamarin.Forms.Xaml;
namespace App2.View
{
[XamlCompilation(XamlCompilationOptions.Compile)] 。
public partial class ExampleListPage : ContentPage >。
{
public ExampleListPage()
{
InitializeComponent()。
BindingContext = new ExampleListViewModel()。
}
}
}
這個頁面的視圖模型如下:
using App2.Models;
using System.Models;;;;;;;;;。
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Threading.Tasks;
namespaceApp2.ViewModels
{
public class ExampleListViewModel : BindableObject // < this is required for mvvm
{
public ExampleListViewModel()
{
//這里提到的按鈕也需要在下面宣告為icommands。
ListElementSelect = new Command(ElementSelect)。
RefreshCommand = new Command(OnRefresh);
AddElement = new Command(OnAddElement);
OnRefresh(); //不確定是否可以在這里呼叫。
}
// <summary>
//私有元素在此。
// </summary>/span>
private example _example;
private List<example> _exampleList = new List< example>()。
private bool _isBusy = false。
private example _selectedElement;
// <summary>
//公共元素在此。
// </summary>/span>
//
//這確實修復了編譯錯誤,但仍然不能顯示文本。
//public int ID {
//get => this.Example.ID;
//}
//private string _desc;
//public string Desc {
//get => this.Example.Desc;
//}
public example SelectedElement
{
get => _selectedElement;
set
{
if (value != null)
{
Application.Current.MainPage.DisplayAlert("Selected", value.ID value.Content, "x") 。
value = null;
}
_selectedElement = value;
OnPropertyChanged();
}
public example Example
{
get => _example;
set
{
_example = value;
OnPropertyChanged(nameof(Example))。
}
public List< example> ExampleList
{
get => _exampleList;
set
{
_exampleList = value;
OnPropertyChanged(nameof(ExampleList))。
}
}
public bool IsBusy
{
get => _isBusy;
set
{
if (value == _isBusy) return;
_isBusy = value;
OnPropertyChanged(nameof(IsBusy))。
}
}
// <summary>
//按鈕命令在此。
// </summary>/span>
public ICommand ListElementSelect { get; }
public ICommand RefreshCommand { get; }
public ICommand AddElement { get; }
// <summary>
//這里的功能。
// </summary>/span>
//
async void ElementSelect()
{
}
async void OnAddElement()
{
}
async void OnRefresh()
{
OnBusy()。
await Load(); //從API服務請求串列。
await Task.Delay(2000); //artifical package delay。
OnBusy()。
}
void OnBusy() //翻轉實體從真或假--用于執行請求時顯示加載符號。
{
switch (IsBusy)
{
case true:
IsBusy = false;
break;
case false:
IsBusy = true;
break;
}
}
async Task Load()
{
string searchTerm = ";
Expression<Func<例子,bool>> searchLambda = x => x.Content.Contains("SearchTerm"/span>); //instanciate searchLambda
string stringLambda = searchLambda.ToString(). Replace("SearchTerm", $"{searchTerm}"); //crashes here.
searchLambda = DynamicExpressionParser.ParseLambda<example, bool>(new ParsingConfig(), true, stringLambda) 。
ExampleList = await App.DataService.GetAllAsync<example>()。
//listView.ItemsSource = ExampleList;。
}
}
}
這就是例子類:
using System.Collections.Generic; using System.ComponentModel; using App2.ViewModels; using Newtonsoft.Json.ComponentModel; using App2.ViewModels; namespaceApp2.Models { public class example { { public event PropertyChangedEventHandler PropertyChanged; //this does event things[/span public int ID { get; set; } public string Content { get; set; } public bool Status { get; set; } public string WebLink { get; set; } [] //需要newtonsoft。 public string Desc { //用于串列顯示,不轉到后臺。 get { return ID.ToString() " - "/span> Content.ToString() " - "/span> Status.ToString()。 } } public example(int id, string content, bool status, string webLink) { this.ID = id; this.Content = content; this.Status = status; this.WebLink = webLink; } public example() { } public string toString() { return ID.ToString() " - "/span> Content.ToString() " - "/span> Status.ToString() " - "/span> WebLink.ToString() 。 } } }uj5u.com熱心網友回復:
你不需要洗掉頁面級的x:DataType屬性。你可以通過在DataTemplate本身上指定x:DataType屬性來告知編譯器DataTemplate的DataType(注意,你需要添加一個xmlns參考來實作,類似于你的xmlns:viewmodels參考):
<DataTemplate x:DataType="models:example"> /span>
<TextCell Text="{Binding ID}" Detail="{Binding Example. Desc}"/>
</DataTemplate>/span>
至于串列中沒有顯示任何專案,我會仔細檢查這一行:
ExampleList = await App.DataService.GetAllAsync< example> ();
是回傳一個非空的專案串列。由于你的問題中沒有包括這個方法,我不能對它的作用做出任何假設。
最后還有一點:你不一定需要在你的ViewModel中繼承BindableObject以使MVVM作業;只需要INotifyPropertyChanged就足夠了。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/317279.html
標籤:
上一篇:startForeground錯誤的通知:無效的服務通知
下一篇:Xamarin專案未安裝
