Xamarin,将View Model与ViewCell一起使用会搞乱ViewModel绑定

时间:2019-12-03 14:31:26

标签: listview xamarin binding viewmodel datatemplate

我一直在仔细阅读我为此撰写标题时获得的所有建议,但没有一个可以帮助我解决我的问题。由于这是我的第一个问题,如果我问错了,您必须原谅我,请告诉我是否需要ellaborate。

但是我在Xamarin中使用ListView。 可以通过在ItemSource中设置一个List来填充listView,该List包含一个扩展ViewCell类的我的类,这基本上如下所示。

问题

我遇到的问题是将ViewModel用于MeasurePointView.xaml.cs类。尝试访问MeasurePointViewModel中的任何属性(将MeasurePointView.xaml.cs的BindingContext设置为BindingContext)时,例如,我从调试器获取[0:] Binding: 'MeasurePointProps' property not found on 'Mobile.Pages.MeasurePointView', target property: 'Xamarin.Forms.Label.Text',当然,屏幕上也没有任何显示。

所以我的问题是:如何设置ViewCell类“ MeasurePointView”和ViewModel“ MeasurePointViewViewModel”之间的绑定以使它正常工作?

另外,请让我知道我可能误解了数据绑定的严重性。只是我一直在使用这种方法在整个应用程序中工作,除了这里。

只需澄清一下: 页面扩展了BasePage(扩展了ContentPage) 而且Viewmodels源自BaseViewModel(基本上实现了INotifyPropertyChanged)

ListOneView.xaml.cs

using Mobile.Controls;
using Mobile.Pages;
using Mobile.ViewModels;
using System.Collections.ObjectModel;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace Mobile.Views {
  [XamlCompilation(XamlCompilationOptions.Compile)]
  public partial class ListOneView : BasePage {

    public ListView ListView;

    public ObservableCollection<MeasurePoint> MeasurePointList { get; set; }

    public ListOneView(ObservableCollection<MeasurePoint> list) {
      MeasurePointList = list;
      InitializeComponent();
      InitializeBindings();
      InitializeMeasurePoints();
    }

    public void InitializeBindings() {
      BindingContext = ViewModel = new ListOneViewViewModel(MeasurePointList);
    }

    private void InitializeMeasurePoints() {
      ListView = MeasurePointListView;
      MeasurePointListView.ItemTemplate = new DataTemplate(typeof(MeasurePointView));
      MeasurePointListView.ItemsSource = (ViewModel as ListOneViewViewModel).MeasurePointViewList;
    }
}


ListOneView.xaml


<?xml version="1.0" encoding="utf-8" ?>
<pages:BasePage
    xmlns:pages="clr-namespace:Mobile.Pages"
    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"
    mc:Ignorable="d"
    x:Class="Mobile.Views.ListOneView"
    BackgroundColor="{StaticResource BackgroundGrey}">
    <ContentPage.Resources>
        <ResourceDictionary>
            <Style TargetType="Label">
                <Setter Property="FontSize" Value="12" />
                <Setter Property="TextColor" Value="Black" />
            </Style>
        </ResourceDictionary>
    </ContentPage.Resources>

    <ListView
        x:Name="MeasurePointListView"
        BackgroundColor="{StaticResource BackgroundGrey}"
        HasUnevenRows="True">
        <!--Empty-->
    </ListView>

</pages:BasePage>


ListOneViewViewModel.cs


using Mobile.Controls;
using Mobile.Pages;
using System.Collections.ObjectModel;

namespace Mobile.ViewModels {
  public class ListOneViewViewModel : BaseViewModel {

    public ObservableCollection<MeasurePointView> MeasurePointViewList { get; set; }

    public ListOneViewViewModel(ObservableCollection<MeasurePoint> measurePointList) {
      if (MeasurePointViewList == null)
        MeasurePointViewList = new ObservableCollection<MeasurePointView>();

      foreach (MeasurePoint mp in measurePointList) {
        MeasurePointViewList.Add(new MeasurePointView() {
          MeasurePoint = mp
        });
      }
    }
  }
}

MeasurePointView.xaml.cs


using Mobile.Controls;
using Mobile.ViewModels;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace Mobile.Pages {
  [XamlCompilation(XamlCompilationOptions.Compile)]
  public partial class MeasurePointView : ViewCell {
    public MeasurePoint MeasurePoint { get; set; }
    public MeasurePointView() {
      InitializeComponent();
      InitializeBindings();
    }

    private void InitializeBindings() {
      BindingContext = new MeasurePointViewViewModel() {
        MeasurePointProps = this.MeasurePoint
      };
    }
  }

  public class MeasurePointViewViewModel : BaseViewModel {
    public MeasurePoint MeasurePointProps { get; set; }
  }
}

MeasurePointView.xaml


<?xml version="1.0" encoding="UTF-8"?>
<ViewCell
    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"
    x:Class="Mobile.Pages.MeasurePointView"
    mc:Ignorable="d">
    <ViewCell.View>
        <ContentView>
            <Label Text="{Binding MeasurePointProps.Title}" />
        </ContentView>
    </ViewCell.View>
</ViewCell>

2 个答案:

答案 0 :(得分:0)

我认为您有点复杂了。将ListView与视图单元一起使用非常简单。您可以创建ListView并定义自己的ItemTemplate,然后直接在其中使用ViewCell。您还可以创建自己的自定义视图单元格并使用它。

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="demoListView.ImageCellPage">
    <ContentPage.Content>
        <ListView  x:Name="listView">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <StackLayout BackgroundColor="#eee" Orientation="Vertical">
                            <StackLayout Orientation="Horizontal">
                                <Image Source="{Binding image}" />
                                <Label Text="{Binding title}" TextColor="#f35e20" />
                                <Label Text="{Binding subtitle}" HorizontalOptions="EndAndExpand" TextColor="#503026" />
                            </StackLayout>
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </ContentPage.Content>
</ContentPage>

有关如何将ListView与视图单元一起使用的更多信息,请参见下面的链接。

https://docs.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/listview/customizing-cell-appearance

答案 1 :(得分:0)

  

例如,我正在获取:[0:]绑定:在'Mobile.Pages.MeasurePointView'上找不到'MeasurePointProps'属性,在调试器中没有找到目标属性:'Xamarin.Forms.Label.Text',当然什么都没有显示在屏幕上。

MeasurePoint.cs

public class MeasurePoint
{
    public string Title { get; set; }
    public string Point { get; set; }

}

MeasurePointViewViewModel.cs

public class MeasurePointViewViewModel : INotifyPropertyChanged
{
    public MeasurePointViewViewModel()
    {
        MeasurePointProps = new MeasurePoint() { Point = "B", Title = "2" };
    }

    private MeasurePoint _MeasurePointProps;
    public MeasurePoint MeasurePointProps
    {
        get { return _MeasurePointProps; }
        set
        {
            _MeasurePointProps = value;
            OnPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged([CallerMemberName]string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

解决方案1:

如果要绑定MeasurePointProps.Title,可以直接用MeasurePointViewViewModel设置BindingContent。

Xaml:

<Label Text="{Binding MeasurePointProps.Title}"/>

代码:

  public MainPage()
    {
        InitializeComponent();
        InitializeBindings();
    }

    private void InitializeBindings()
    {
        BindingContext = new MeasurePointViewViewModel();
    }

解决方案2:

如果要绑定标题,则可以查看下面的代码。

Xaml:

<Label Text="{Binding Title}"/>

代码:

public MainPage()
    {
        InitializeComponent();
        InitializeBindings();
    }

    private void InitializeBindings()
    {
        //BindingContext = new MeasurePointViewViewModel();
        BindingContext = new MeasurePointViewViewModel().MeasurePointProps;
    }