ListView 单元格绑定未在集合中找到方法
ListView Cell Binding not finding Methods in Collection
我正在尝试使用 MVVM and ListView for the first time. I am working from
我的 ViewModel 如下所示:
public class CodeTableViewModel : BaseViewModel
{
public static ObservableCollection<CodeTableRow> CodeTable { get; set; }
public CodeTableViewModel()
{
}
public class CodeTableRow : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
int codePoint;
public CodeTableRow(int point)
{
codePoint = point;
}
public string Decimal
{
get
{
return codePoint.ToString("D");
}
}
public string Hex
{
get
{
return codePoint.ToString("X2");
}
}
public string Ascii
{
get
{
return ((char)codePoint).ToString();
}
}
...
我的XAML看起来像这样
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:viewmodels="clr-namespace:RefCard.ViewModels"
x:Class="RefCard.Views.CodeTablePage"
Title="Code Table">
<ContentPage.Content>
<ListView x:DataType="viewmodels:CodeTableViewModel" ItemsSource="{Binding CodeTable}">
<ListView.Header>
<Grid BackgroundColor="Black">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label Text="Dec" HorizontalOptions="Fill" Grid.Column="0" FontSize="Medium" FontAttributes="Bold" BackgroundColor="MediumBlue" TextColor="White" HorizontalTextAlignment="Center" Margin="1"/>
<Label Text="Hex" HorizontalOptions="Fill" Grid.Column="1" FontSize="Medium" FontAttributes="Bold" BackgroundColor="MediumBlue" TextColor="White" HorizontalTextAlignment="Center" Margin="0"/>
<Label Text="ASCII" HorizontalOptions="Fill" Grid.Column="2" FontSize="Medium" FontAttributes="Bold" BackgroundColor="MediumBlue" TextColor="White" HorizontalTextAlignment="Center" Margin="0"/>
</Grid>
</ListView.Header>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid BackgroundColor="Black">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Text ="{Binding Decimal}" HorizontalOptions="Fill" BackgroundColor="LightBlue" HorizontalTextAlignment="Center" Margin="1" TextColor="Black"></Label>
<Label Grid.Column="1" Text ="{Binding Hex}" HorizontalOptions="Fill" BackgroundColor="LightBlue" HorizontalTextAlignment="Center" Margin="0"></Label>
<Label Grid.Column="2" Text ="{Binding Ascii}" HorizontalOptions="Fill" BackgroundColor="LightBlue" HorizontalTextAlignment="Center" Margin="0"></Label>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage.Content>
</ContentPage>
在页面构造函数中我做了 CodeTableViewModel.CodeTable = new ObservableCollection<CodeTableViewModel.CodeTableRow>();
和一堆添加。
我尝试破解了很多变体,但基本错误是:
XFC0045 Binding: Property "Decimal" not found on "RefCard.ViewModels.CodeTableViewModel". RefCard C:\Users\Charles\source\repos\RefCard\RefCard\Views\CodeTablePage.xaml 38
我该如何解决?
简而言之,这是您的 ListView 项的不正确的数据类型。
在个人中定义您的模型class
(不需要为模型 classes 实现 INotifyPropertyChanged,但在 BaseViewModel 中实现)
namespace YourProj.Models
{
public class CodeTableRow
{
public string Decimal { get; set; }
...
}
}
在 CodeTableViewModel 中定义 属性 的 CodeTableRow
public class CodeTableViewModel : BaseViewModel
{
public static ObservableCollection<CodeTableRow> CodeTable { get; set; }
public CodeTableViewModel()
{
}
private CodeTableRow _codeTableRow;
public CodeTableRow CodeTableRow
{
get => _codeTableRow;
set => SetProperty(ref _codeTableRow, value);
}
}
更正 ListView 项的数据类型
<ContentPage
xmlns:models="clr-namespace:YourProj.Models"
...>
<ListView ...>
<ListView.ItemTemplate>
<DataTemplate x:DataType="models:CodeTableRow">
....
</ListView>
根据您的代码, 给您三点建议。
首先,你不需要添加x:DataType="viewmodels:CodeTableViewModel"
,因为ListView的ItemsSource="{Binding CodeTable}",然后是CodeTableRow的CodeTable列表。
其次,来自这篇文档Model-View-ViewModel Pattern,
视图—视图负责定义用户在屏幕上看到的内容的结构、布局和外观。
ViewModel—视图模型实现视图可以数据绑定到的属性和命令,并通过更改通知事件通知视图任何状态更改。
模型—模型class是封装应用程序数据的非可视class模型。
所以我建议您不要在您的 ViewModel class 中添加模型 class。这是两个独立的 classes.
public class CodeTableViewModel
{
public ObservableCollection<CodeTableRow> CodeTable { get; set; }
public CodeTableViewModel()
{
CodeTable = new ObservableCollection<CodeTableRow>();
}
}
public class CodeTableRow : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
int codePoint;
public CodeTableRow(int point)
{
codePoint = point;
}
public string Decimal
{
get
{
return codePoint.ToString("D");
}
}
public string Hex
{
get
{
return codePoint.ToString("X2");
}
}
public string Ascii
{
get
{
return ((char)codePoint).ToString();
}
}
}
通常,我们在 ViewModel class 中获取一些数据,然后将 ViewModel 绑定到当前 contentPage 的 BindingContext。
public class CodeTableViewModel
{
public ObservableCollection<CodeTableRow> CodeTable { get; set; }
public CodeTableViewModel()
{
CodeTable = new ObservableCollection<CodeTableRow>()
{
new CodeTableRow(12),
new CodeTableRow(18),
new CodeTableRow(19),
new CodeTableRow(121),
new CodeTableRow(124)
};
}
}
public Page22()
{
InitializeComponent();
this.BindingContext = new CodeTableViewModel();
}
如果你还想在ContentPage的构造函数中获取数据,可以看看下面的代码,但我不建议这样做。
public partial class Page22 : ContentPage, INotifyPropertyChanged
{
private CodeTableViewModel _viewmodel;
public CodeTableViewModel viewmodel
{
get { return _viewmodel; }
set
{
_viewmodel = value;
RaisePropertyChanged("viewmodel");
}
}
public Page22()
{
InitializeComponent();
viewmodel = new CodeTableViewModel();
viewmodel.CodeTable = new ObservableCollection<CodeTableRow>()
{
new CodeTableRow(12),
new CodeTableRow(18),
new CodeTableRow(19),
new CodeTableRow(121),
new CodeTableRow(124)
};
this.BindingContext = viewmodel;
}
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
我正在尝试使用 MVVM and ListView for the first time. I am working from
我的 ViewModel 如下所示:
public class CodeTableViewModel : BaseViewModel
{
public static ObservableCollection<CodeTableRow> CodeTable { get; set; }
public CodeTableViewModel()
{
}
public class CodeTableRow : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
int codePoint;
public CodeTableRow(int point)
{
codePoint = point;
}
public string Decimal
{
get
{
return codePoint.ToString("D");
}
}
public string Hex
{
get
{
return codePoint.ToString("X2");
}
}
public string Ascii
{
get
{
return ((char)codePoint).ToString();
}
}
...
我的XAML看起来像这样
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:viewmodels="clr-namespace:RefCard.ViewModels"
x:Class="RefCard.Views.CodeTablePage"
Title="Code Table">
<ContentPage.Content>
<ListView x:DataType="viewmodels:CodeTableViewModel" ItemsSource="{Binding CodeTable}">
<ListView.Header>
<Grid BackgroundColor="Black">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label Text="Dec" HorizontalOptions="Fill" Grid.Column="0" FontSize="Medium" FontAttributes="Bold" BackgroundColor="MediumBlue" TextColor="White" HorizontalTextAlignment="Center" Margin="1"/>
<Label Text="Hex" HorizontalOptions="Fill" Grid.Column="1" FontSize="Medium" FontAttributes="Bold" BackgroundColor="MediumBlue" TextColor="White" HorizontalTextAlignment="Center" Margin="0"/>
<Label Text="ASCII" HorizontalOptions="Fill" Grid.Column="2" FontSize="Medium" FontAttributes="Bold" BackgroundColor="MediumBlue" TextColor="White" HorizontalTextAlignment="Center" Margin="0"/>
</Grid>
</ListView.Header>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid BackgroundColor="Black">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Text ="{Binding Decimal}" HorizontalOptions="Fill" BackgroundColor="LightBlue" HorizontalTextAlignment="Center" Margin="1" TextColor="Black"></Label>
<Label Grid.Column="1" Text ="{Binding Hex}" HorizontalOptions="Fill" BackgroundColor="LightBlue" HorizontalTextAlignment="Center" Margin="0"></Label>
<Label Grid.Column="2" Text ="{Binding Ascii}" HorizontalOptions="Fill" BackgroundColor="LightBlue" HorizontalTextAlignment="Center" Margin="0"></Label>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage.Content>
</ContentPage>
在页面构造函数中我做了 CodeTableViewModel.CodeTable = new ObservableCollection<CodeTableViewModel.CodeTableRow>();
和一堆添加。
我尝试破解了很多变体,但基本错误是:
XFC0045 Binding: Property "Decimal" not found on "RefCard.ViewModels.CodeTableViewModel". RefCard C:\Users\Charles\source\repos\RefCard\RefCard\Views\CodeTablePage.xaml 38
我该如何解决?
简而言之,这是您的 ListView 项的不正确的数据类型。
在个人中定义您的模型class (不需要为模型 classes 实现 INotifyPropertyChanged,但在 BaseViewModel 中实现)
namespace YourProj.Models { public class CodeTableRow { public string Decimal { get; set; } ... } }
在 CodeTableViewModel 中定义 属性 的 CodeTableRow
public class CodeTableViewModel : BaseViewModel { public static ObservableCollection<CodeTableRow> CodeTable { get; set; } public CodeTableViewModel() { } private CodeTableRow _codeTableRow; public CodeTableRow CodeTableRow { get => _codeTableRow; set => SetProperty(ref _codeTableRow, value); } }
更正 ListView 项的数据类型
<ContentPage xmlns:models="clr-namespace:YourProj.Models" ...> <ListView ...> <ListView.ItemTemplate> <DataTemplate x:DataType="models:CodeTableRow"> .... </ListView>
根据您的代码,
首先,你不需要添加x:DataType="viewmodels:CodeTableViewModel"
,因为ListView的ItemsSource="{Binding CodeTable}",然后是CodeTableRow的CodeTable列表。
其次,来自这篇文档Model-View-ViewModel Pattern,
视图—视图负责定义用户在屏幕上看到的内容的结构、布局和外观。
ViewModel—视图模型实现视图可以数据绑定到的属性和命令,并通过更改通知事件通知视图任何状态更改。
模型—模型class是封装应用程序数据的非可视class模型。
所以我建议您不要在您的 ViewModel class 中添加模型 class。这是两个独立的 classes.
public class CodeTableViewModel
{
public ObservableCollection<CodeTableRow> CodeTable { get; set; }
public CodeTableViewModel()
{
CodeTable = new ObservableCollection<CodeTableRow>();
}
}
public class CodeTableRow : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
int codePoint;
public CodeTableRow(int point)
{
codePoint = point;
}
public string Decimal
{
get
{
return codePoint.ToString("D");
}
}
public string Hex
{
get
{
return codePoint.ToString("X2");
}
}
public string Ascii
{
get
{
return ((char)codePoint).ToString();
}
}
}
通常,我们在 ViewModel class 中获取一些数据,然后将 ViewModel 绑定到当前 contentPage 的 BindingContext。
public class CodeTableViewModel
{
public ObservableCollection<CodeTableRow> CodeTable { get; set; }
public CodeTableViewModel()
{
CodeTable = new ObservableCollection<CodeTableRow>()
{
new CodeTableRow(12),
new CodeTableRow(18),
new CodeTableRow(19),
new CodeTableRow(121),
new CodeTableRow(124)
};
}
}
public Page22()
{
InitializeComponent();
this.BindingContext = new CodeTableViewModel();
}
如果你还想在ContentPage的构造函数中获取数据,可以看看下面的代码,但我不建议这样做。
public partial class Page22 : ContentPage, INotifyPropertyChanged
{
private CodeTableViewModel _viewmodel;
public CodeTableViewModel viewmodel
{
get { return _viewmodel; }
set
{
_viewmodel = value;
RaisePropertyChanged("viewmodel");
}
}
public Page22()
{
InitializeComponent();
viewmodel = new CodeTableViewModel();
viewmodel.CodeTable = new ObservableCollection<CodeTableRow>()
{
new CodeTableRow(12),
new CodeTableRow(18),
new CodeTableRow(19),
new CodeTableRow(121),
new CodeTableRow(124)
};
this.BindingContext = viewmodel;
}
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}