我正在渲染此ListView
<StackLayout>
<Label Text="Test"/> //This Label is getting rendered
<ListView ItemsSource="{Binding MusicList,Mode=TwoWay}"
HasUnevenRows="True"
IsPullToRefreshEnabled="True"
CachingStrategy="RecycleElement"
SeparatorColor="DarkGray">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Label Text="{Binding Name}" TextColor="Black"/>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
将ItemsSource绑定到ObservableCollection<Music>
中可用的ViewModel
。这就是我绑定ViewModel
public MainPage()
{
BindingContext = new MainViewModel();
InitializeComponent();
}
这是我的ViewModel
,这里我调用API方法来获取数据。
private ObservableCollection<Music> _MusicList=new ObservableCollection<Music>();
public ObservableCollection<Music> MusicList
{
get { return _MusicList; }
set
{
if (_MusicList != value)
{
_MusicList = value;
OnPropertyChanged("_MusicList");
}
}
}
public MainViewModel()
{
api = new ApiHelper();
GetSongs();
}
public async void GetSongs()
{
_MusicList = new ObservableCollection<Music>(await api.GetMusicListAsync());
}
数据进入ObservableCollection<Music>
更新
仅出于测试目的,我尝试绑定简单的字符串列表ListStrings = new List<string> {"A","B","C","D","E","F" };
,但它也没有显示。
更新 现在,我重写onAppearing方法并初始化了我的列表,并将ListView ItemsSource设置为它。并且它现在可以工作了。但是不知道为什么它不能与绑定一起工作。
答案 0 :(得分:3)
有些事情可能有问题。
ItemsSource="{Binding MusicList,Mode=TwoWay}"
有充分的理由使其成为TwoWay吗?如果没有,请不要这样做。BindingContext
之后设置InitializeComponent();
获取数据时请勿创建新的ObservableCollection
。通过创建新的集合,您将失去数据绑定。而是这样更改它:
public async void GetSongs()
{
var result = await api.GetMusicListAsync();
foreach (var r in result)
_MusicList.Add(r);
}
答案 1 :(得分:1)
我认为您在加错财产方面犯了错误:
import { StyleSheet, Dimensions } from 'react-native';
import Colours from '../models/Colours';
const MARGIN = 20;
const h = Dimensions.get("window").height;
const w = Dimensions.get("window").width;
const pageH = h - 65 - 50 - 5; // header, tabs, safe
const Styles = StyleSheet.create({
dark: {
backgroundColor: Colours.DARK
},
black: {
backgroundColor: Colours.BLACk
},
page: {
//flex: 1,
//flexDirection: 'row'.
backgroundColor: Colours.DARK
},
centerContainer: {
flex: 1,
justifyContent: "center",
alignItems: "center"
},
fullPage: {
flex: 1,
justifyContent: "center",
alignItems: "center",
height: pageH
},
modalBG: {
position: 'absolute',
top: 0,
left: 0,
flex: 1,
width: w,
height: h,
justifyContent: "center",
alignItems: "center",
backgroundColor: Colours.RGBA_BLACK
},
centerBlackMargin: {
flex: 1,
justifyContent: "center",
alignItems: "center",
margin: 1,
backgroundColor: Colours.RGBA_BLACK
},
list: {
borderColor: Colours.DARK
},
listTitle: {
color: Colours.WHITE,
fontSize: 16
},
listItem: {
backgroundColor: Colours.DARK,
borderColor: Colours.DARKER,
borderBottomWidth: 1,
height: 60
//borderBottomColor: '#bbb',
//borderTopWidth: 0,
//borderBottomWidth: 0
//StyleSheet.hairlineWidth,
},
listItemPress: {
borderColor: Colours.DARKER
},
input: {
color: Colours.GREY
//height: 60
//borderBottomColor: '#bbb',
//borderTopWidth: 0,
//borderBottomWidth: 0
//StyleSheet.hairlineWidth,
},
textarea: {
color: Colours.GREY,
fontSize: 18,
marginLeft: 14,
marginTop: 15,
paddingLeft: 0,
paddingRight: 15,
borderColor: 'transparent',
borderBottomWidth: 1,
borderBottomColor: Colours.DARKER
},
listItemContainer: {
backgroundColor: Colours.DARK
},
listCols: {
flex: 1,
flexDirection: 'row',
paddingLeft: 10
},
subtitle: {
color: Colours.DARKGREY,
backgroundColor: Colours.DARK,
fontSize: 12
},
title: {
color: Colours.WHITE,
fontSize: 18
},
headerTitle: {
fontSize: 24,
color: Colours.WHITE
},
headerSide:{
flex: 0,
flexBasis: 48
},
headerBody:{
flex: 1,
},
bigTitle: {
fontSize: 48,
color: Colours.WHITE
},
midTitle: {
fontSize: 36,
color: Colours.WHITE
},
smallTitle: {
fontSize: 12,
color: Colours.DARKGREY
},
checkbox: {
marginRight: MARGIN
},
// input: {
// width: 200,
// height: 40,
// fontSize: 24,
// backgroundColor: Colours.RED
// },
sendButton: {
marginTop: 25,
paddingRight: 15,
paddingLeft: 15,
},
sidePadding: {
paddingRight: MARGIN,
paddingLeft: MARGIN,
},
trackFooter: {
paddingTop: MARGIN,
paddingRight: MARGIN,
paddingLeft: MARGIN,
},
button: {
color: Colours.WHITE,
fontSize: 18,
backgroundColor: Colours.RED
},
cancelTrack: {
color: Colours.GREY,
textAlign: 'center',
padding: 10
},
textWarn: {
color: Colours.RED,
textAlign: 'center',
marginTop: 5
},
textCenter: {
color: Colours.GREY,
textAlign: 'center',
marginTop: 10,
//fontSize: 21
},
icon: {
color: Colours.GREY
},
bgRed: {
backgroundColor: Colours.RED
},
bgBlue: {
backgroundColor: Colours.BLUE
},
bgYellow: {
backgroundColor: Colours.YELLOW
},
dashNotEnough: {
textAlign: 'center',
fontSize: 21,
color: Colours.DARKGREY
},
dashFooter: {
height:150,
flex: 1,
justifyContent: "center",
alignItems: "center",
//backgroundColor: Colours.YELLOW
},
centeredScreen: {
flex: 1,
justifyContent: "center",
alignItems: "center",
//backgroundColor: Colours.YELLOW
},
centeredScreenCol: {
flex: 1,
flexDirection: 'column',
justifyContent: "center",
alignItems: "center",
//backgroundColor: Colours.BLUE
}
});
export default Styles;
就像@Gerald所说的那样,请听从他的建议,我想补充一下,您可以解决他提到的第三个问题。
如果每次获取数据时都创建一个Observable Collection,则会丢失数据绑定。如果您使用的foreach方法会多次引发集合更改事件,那么如果列表很大,可能对您来说是个问题。
以下扩展收集支持不同类型的收集,并具有重置可观察收集的属性。
在视图模型构造器上,您可以像这样初始化一次集合:
private ObservableCollection<Music> _MusicList=new
ObservableCollection<Music>();
public ObservableCollection<Music> MusicList
{
get { return _MusicList; }
set
{
_MusicList = value;
OnPropertyChanged("MusicList"); //You should raise property change on your Binding variable.
}
}
然后,每当您从API中获取数据时,您都将执行以下操作:
public MusicPageViewModel()
{
MusicsData=new ExtendedCollection<Music>();
}
我希望它可以帮助您实现Observable集合。这是扩展的可观察的集合,您可以使用它,并在需要时进一步扩展它:
public GetMusicsData()
{
MusicsData.Reset(YourApi.GetMusics());
}
答案 2 :(得分:1)
今天我找到了解决方案。
public MainPage()
{
InitializeComponent();
BindingContext = this; //Added this
}
仅在构造函数中添加了BindingContext = this;
。我不知道Xamarin到底出了什么问题。
答案 3 :(得分:0)
此问题已通过更改在观察对象中声明属性的方式解决。示例:
失败
public class MusicItem
{
public string Name;
}
这很成功:
public class MusicItem
{
public string Name {get; set;}
}
Binding 在第一个示例中找不到属性 Name,但在第二个示例中找到了。