我在控件和viewModel之间绑定View元素列表时遇到问题。
我创建了一个ContentView并将其包含在ContentPage中。我需要在ContentView中动态创建Grid.Children,方法是将在ViewModel中创建的BoxView元素列表添加到网格中。
我设法成功绑定了其他控件(例如Label),但是当我尝试绑定视图列表时,出现错误。
导航到包含ContentView的ContentPage时出现第一个错误,该页面没有事件加载,我得到:
System.NullReferenceException:对象引用未设置为对象的实例。
您的应用已进入中断状态,但是由于所有线程都在执行外部代码(通常是系统代码或框架代码),因此没有可显示的代码。
因此,这时我从Control(ContentPage的XAML中的标记)和页面加载中删除了绑定,但是当我启动应该用包含BoxView元素的List填充Control的Grid的方法时,我将无法传递列出到控件,因为此时不存在绑定。
我的问题是,有没有一种方法可以在Xamarin.Forms中的ViewModel和ContentView之间绑定视图列表?还是我正在尝试做一些永远行不通的事情?
当基于ContentPage加载后创建的视图列表渲染网格时,如何刷新ContentView网格?
如果以上都不可行,是否可以在ContentPage的仅加载选项上创建Grid的子级?然后可以将Views List作为参数传递给ContentPage吗?
我这里的一般问题是,我需要根据稍后将基于各种因素输入的数据生成Grid的子代。
我希望可以在实际加载内容页面之后渲染/刷新Grid及其子元素。
这是我现在拥有的代码:
后面的ContentView代码
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class GridView : ContentView
{
public GridView()
{
InitializeComponent();
}
public static readonly BindableProperty ViewProperty = BindableProperty.Create(nameof(ViewList), typeof(List<View>), typeof(GridView));
public List<View> ViewList
{
get
{
return (List<View>)GetValue(ViewProperty);
}
set
{
SetValue(ViewProperty, value);
}
}
}
ContentView XAML
<AbsoluteLayout>
<Grid x:Name="RenderedGrid"
x:FieldModifier="public"
ColumnSpacing="1"
AbsoluteLayout.LayoutBounds="0, 0, 1, 1"
AbsoluteLayout.LayoutFlags="All">
</Grid>
</AbsoluteLayout>
后面的ContentPage代码
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class GridPage : ContentPage
{
public GridPage ()
{
InitializeComponent ();
BindingContext = new GridPageViewModel(Navigation);
}
}
ContentPage标记
<ScrollView Grid.Row="1">
<local:GridView ViewList="{Binding Path=BindingContext.ViewsList, Source={x:Reference GridPage}}"/>
</ScrollView>
ContentPage的ViewModel
[XamlCompilation(XamlCompilationOptions.Compile)]
public class GridPageViewModel : BaseGridViewModel
{
public Classes _Classes;
public GridView _gridView = new GridView();
public ICommand RenderGridCommand { get; private set; }
public GridPageViewModel(INavigation navigation)
{
_navigation = navigation;
RenderGridCommand = new Command(() => StartRender());//used when button is hit, not when page loads.
}
public void StartRender()
{
CreateGrid();
}
public void CreateGrid()
{
//List<View> views = new List<View>();
for (int i = 0; i < SomeProvidedCustomDataList.Count(); i++)
{
BoxView boxView = new BoxView
{
Color = Color.Accent,
HeightRequest = SomeProvidedCustomDataList[i].Height,
VerticalOptions = LayoutOptions.End,
StyleId = SomeProvidedCustomDataList[i].Name
};
boxView.GestureRecognizers.Add(tapGesture);
ViewsList.Add(boxView);
}
//Add list of boxViews to Grid
_gridView.RenderedGrid.Children.AddHorizontal(_gridView.ViewList);
}
List<View> _viewsList = new List<View>();
public List<View> ViewsList
{
get => _viewsList;
set
{
_viewsList = value;
NotifyPropertyChanged("ViewsList");
}
}
}