Xamarin形成列表中的列表(使用棱镜导航)



问题是,我似乎无法将NavigationService传递给ModulesModel以用于导航到AnotherView项,而我只能将其传递给SectionModel。但我只能将NavigationService传递给父ListView(我不想要(,它需要通过子ListView传递。救命!!!

UI代码

      <ListView
      SeparatorColor="Transparent"
      VerticalOptions="FillAndExpand"
      HorizontalOptions="FillAndExpand"
      ItemsSource="{Binding Data}"
      HasUnevenRows="True">
      <ListView.Header>
        <local:ModuleCourseHeaderViewControl />
      </ListView.Header>
      <ListView.ItemTemplate>
        <DataTemplate>
          <ViewCell>
            <Frame
              HasShadow="False"
              BackgroundColor="{StaticResource BiancaBackgroundColour}">
              <Frame.CornerRadius>
                <OnIdiom
                  x:TypeArguments="x:Single"
                  Phone="0"
                  Tablet="15" />
              </Frame.CornerRadius>
              <Frame.Margin>
                <OnIdiom
                  x:TypeArguments="Thickness"
                  Phone="0,10"
                  Tablet="20,10" />
              </Frame.Margin>
              <StackLayout>
                <Label
                  FontFamily="{StaticResource LatoRegularFont}"
                  TextColor="{StaticResource MediumGold}"
                  Text="{Binding Title}">
                  <Label.FontSize>
                    <OnIdiom
                      x:TypeArguments="x:Double"
                      Phone="15"
                      Tablet="17" />
                  </Label.FontSize>
                </Label>
                <flv:FlowListView
                  BackgroundColor="Transparent"
                  SeparatorVisibility="None"
                  HasUnevenRows="False"
                  FlowColumnCount="{DynamicResource ModuleFlowColumnCount}"
                  RowHeight="{DynamicResource RiseCardHeight}"
                  FlowItemsSource="{Binding Modules}">
                  <flv:FlowListView.FlowColumnTemplate>
                    <OnIdiom
                      x:TypeArguments="DataTemplate">
                      <OnIdiom.Phone>
                        <DataTemplate>
                          <local:ModuleCourseCardPhoneControl>
                            <local:ModuleCourseCardPhoneControl.GestureRecognizers>
                              <TapGestureRecognizer
                                CommandParameter="{Binding}"
                                Command="{Binding ItemSelectedCommand}" />
                            </local:ModuleCourseCardPhoneControl.GestureRecognizers>
                          </local:ModuleCourseCardPhoneControl>
                        </DataTemplate>
                      </OnIdiom.Phone>
                      <OnIdiom.Tablet>
                        <DataTemplate>
                          <local:ModuleCourseCardControl>
                            <local:ModuleCourseCardControl.GestureRecognizers>
                              <TapGestureRecognizer
                                CommandParameter="{Binding}"
                                Command="{Binding ItemSelectedCommand}" />
                            </local:ModuleCourseCardControl.GestureRecognizers>
                          </local:ModuleCourseCardControl>
                        </DataTemplate>
                      </OnIdiom.Tablet>
                    </OnIdiom>
                  </flv:FlowListView.FlowColumnTemplate>
                </flv:FlowListView>
              </StackLayout>
            </Frame>
          </ViewCell>
        </DataTemplate>
      </ListView.ItemTemplate>
    </ListView>

型号-代码

public class NewModuleModel
{
    public IList<SectionModel> Sections { get; set; }
    public int ActiviyId { get; set; }
    public string CourseTitle { get; set; }
}
public class SectionModel
{
    public string Title { get; set; }
    public IList<ModulesModel> Modules { get; set; }
    public INavigationService NavigationService { get; set; }
}
public class ModulesModel
{
    public int ModuleId { get; set; }
    public string Title { get; set; }
    public string Description { get; set; }
    public string ModuleImageUrl { get; set; }
    public double Progress { get; set; }
    public double RoundedProgress
    {
        get
        {
            var p = Math.Round(Progress * 100, 0);
            return p;
        }
    }
    public DateTime? LastActivityDTUtc { get; set; }
    public DateTime? CompletedDate { get; set; }
    public string EstimatedDuration { get; set; }
    public int AssetCount { get; set; }
    public int? NavigationAssetID { get; set; }
    public int ActiviyId { get; set; }
    public string CourseTitle { get; set; }
    public int? NavigationAssetContentType { get; set; }
    public string Status
    {
        get
        {
            var result = string.Empty;
            if (CompletedDate != null)
            {
                var c = String.Format("{0:d MMMM yyyy}", CompletedDate);
                result = "Completed on " + c;
            }
            else if (LastActivityDTUtc != null)
            {
                var l = String.Format("{0:d MMMM yyyy}", LastActivityDTUtc);
                result = "Last Activity on " + l;
            }
            else
            {
                result = "New";
            }
            return result;
        }
    }

    public ModulesModel()
    {
        
        ItemSelectedCommand = new DelegateCommand<ModulesModel>(this.OnCardItemSelectedCommand);
    }

    private void OnCardItemSelectedCommand(ModulesModel module)
    {
        if (module.NavigationAssetContentType == 28 && module.AssetCount == 1)
        {
            var navigationParams = new NavigationParameters();
            navigationParams.Add("AssetContentId", module.NavigationAssetID);
            navigationParams.Add("AssetActivityId", module.ActiviyId);
            navigationParams.Add("AssetModuleId", module.ModuleId);
            navigationParams.Add("ParamCourseTitle", module.CourseTitle);
            navigationParams.Add("ParamModuleTitle", module.Title);
            Preferences.Set("NavFromModulePage", true);
            NavigationService.NavigateAsync("AssetWebViewPage", navigationParams, true, false).Forget();
        }
        else
        {
            var navigationParams = new NavigationParameters();
            navigationParams.Add("ParamModuleId", module.ModuleId);
            navigationParams.Add("ParamActivityId", module.ActiviyId);
            navigationParams.Add("ParamCourseTitle", module.CourseTitle);
            Preferences.Set("NavFromModulePage", false);
            //NavigationService.NavigateAsync("ModuleAssetPage", navigationParams, true, false);
        }
    }
    public DelegateCommand<ModulesModel> ItemSelectedCommand { get; set; }
}

}

ViewModel-代码

    private async void LoadData()
    {           
            this.ExecuteAsyncTask(async () =>
            {
                var result = await this.ModuleService.GetNewModuleAsync(ActivityID);
                if (result != null)
                {
                    CourseTitle = result.CourseTitle;
                    CourseDescription = result.CourseDescription;
                    CourseImageUrl = result.CourseImageUrl;
                    DurationInSeconds = result.DurationInSeconds;
                    DurationAsReadableString = result.DurationAsReadableString;
                    DisplayDescription = result.DisplayDescription;
                    Progress = Math.Round(result.Progress * 100, 0);
                    StartDateUTC = result.StartDateUTC;
                    EnrolmentDate = result.EnrolmentDate;
                    LastActivityDate = result.LastActivityDate;
                    foreach (var item in result.Sections)
                    {
                        var itemToAdd = new SectionModel
                        {
                            Title = item.Title,                  
                            Modules = item.Modules,
                            NavigationService = navigationService
                        };
                        Device.BeginInvokeOnMainThread(() =>
                        {
                            this.Data.Add(itemToAdd);
                        });
                    }
                }
                else
                {
                    var exception = new Exception($"Api Error");
                }
            });
        }
    }

请记住,MVVM是模型视图视图视图模型。我们经常看到人们混淆Models和ViewModel。我将通过向您展示适当的体系结构来更间接地回答您的问题。首先我们来看一个ToDoItem模型。

public class ToDoItem
{
    public string Name { get; set; }
    public DateTime Created { get; set; }
    public DateTime Due { get; set; }
}

注意,我们可以通过让我们的模型继承Prism的BindableBase或ReactiveUI的ReactiveObject来简化绑定。我将在这里假设您已经了解如何使这些属性实现INotifyPropertyChanged。

接下来我们需要的是我们的ViewModel,我们会说这是ToDoItemsPageViewModel

public class ToDoItemsPageViewModel : BindableBase
{
    public ObservableCollection<ToDoItem> Items { get; set; }
    public DelegateCommand<ToDoItem> ItemSelectedCommand { get; }
    private async void ItemSelectedCommandExecuted(ToDoItem item)
    {
        // do your navigation here..
    }
}

最后,我们有了ListView或CollectionView(当ListView被弃用时,您应该使用它(。为了简单起见,让我们看看以下内容。

<ListView ItemsSource="{Binding Items}">
  <ListView.ItemTemplate>
    <DataTemplate>
      <StackLayout>
        <Label Text="{Binding Name}" />
        <Button Text="Show"
                Command="{Binding ItemSelectedCommand}"
                CommandParameter="{Binding .}" />
      </StackLayout>
    </DataTemplate>
  </ListView.ItemTemplate>
</ListView>

这里要理解的核心思想是ListView共享其父页面的BindingContext。在我们的DataTemplate中,BindingContext是ToDoItem,而不是ToDoItemsPageViewModel。因此,我们对Name值的绑定将返回单个ToDoItem的名称。虽然我们对CommandParameter的绑定将传入整个ToDoItem,但我们对命令的绑定将不起作用,因为ToDoItem没有这样的命令。

现在让我们看看如何从ViewModel访问命令。

<ListView ItemsSource="{Binding Items}" x:Name="list">
  <ListView.ItemTemplate>
    <DataTemplate>
      <StackLayout>
        <Label Text="{Binding Name}" />
        <Button Text="Show"
                Command="{Binding BindingContext.ItemSelectedCommand,Source={x:Reference list}}"
                CommandParameter="{Binding .}" />
      </StackLayout>
    </DataTemplate>
  </ListView.ItemTemplate>
</ListView>

我们在这里做了三个小的改变。

  • 我们在ListView中添加了一个x:Name。这也可以放在父页面上
  • 我们已将命令绑定从ItemSelectedCommand更改为BindingContext.ItemSelectedCommand
  • 我们已经更改了命令绑定,以包含引用父项(本例中为列表(的Source

这样做的目的是更新一个特定的绑定以查看父绑定。这有效地将BindingContext(针对此单个属性(设置为实际的父级。在这种情况下,您可以将其视为设置为ListView实例的BindingContext。这意味着我们的Binding必须引用BindingContext,然后我们可以点入访问ListView上BindingContext的属性。

相关内容

  • 没有找到相关文章

最新更新