如何在 ListView x:name 内的 Views 中访问 x:name?是不是可以设置不同形式的用户输入?

Posted

技术标签:

【中文标题】如何在 ListView x:name 内的 Views 中访问 x:name?是不是可以设置不同形式的用户输入?【英文标题】:How to access x:name in Views inside ListView x:name? And is it possible to set different forms of user input?如何在 ListView x:name 内的 Views 中访问 x:name?是否可以设置不同形式的用户输入? 【发布时间】:2021-02-16 16:31:37 【问题描述】:

我对 Xamarin 还很陌生,正在制作一个应用程序,其中包含我希望可以选择喜欢/设置为最喜欢的功能的项目列表。

但是由于 ListView 中的 x 名称,我在访问图像视图和按钮视图 x 名称时遇到了问题。我尝试的是通过将 ListView、Button 和 Image 分成不同的网格行来获得与 ListView 中的项目一样多的图像和按钮。 遗憾的是,这导致 Listview 正常填充,但只显示一个图像和一个按钮。

这是我尝试过的: 我的 Xaml:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         xmlns:converters="clr-namespace:MyApp.Converters"
         x:Class="MyApp.MainPage">

<StackLayout Orientation="Horizontal" HorizontalOptions="CenterAndExpand">
    
   <Grid>
    <ListView
        x:Name="CategoryList" 
              SelectionMode="None"
              ItemsSource="Binding FavCategories">
        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>

          <Label Grid.Column="0" Text="Binding ., Converterconverters:ToUpperConverter"></Label>
                    
         </ViewCell>
                
            </DataTemplate>
        </ListView.ItemTemplate>
        
    </ListView>
    <Image x:Name="ImgFav"  
     Grid.Column="2" 
     Source="Binding IsFav"></Image>
    
     <Button x:Name="BtnFav" 
      Grid.Column="3" 
      Text="Binding FavState" 
      Clicked="BtnFav_Clicked"></Button>
                        
  </Grid>
</StackLayout>

</ContentPage>

我的 C#:

public async Task Load()
    
            ApiService apiService = new ApiService();      
            Categories.Clear();


        List<FavCategoryModel> favCategories = new List<FavCategoryModel>();
            var categories = await apiService.GetCategories();

            foreach (var category in categories)
            
                Categories.Add(category);
            
        foreach(var item in Categories)
        

            favCategories.Add(new FavCategoryModel  Category = item, IsFavourite = false );
        
        
            CategoryList.ItemsSource = favCategories.Select(c =>c.Category.ToString()).ToList();
        var isFavourite = favCategories.Select(f => f.IsFavourite);
        foreach(var isfav in favCategories)
        
            if (favCategories.Any(f => f.IsFavourite) == false)
            
                foreach(var category in categories)
                
                
                ImgFav.Source = "nonFav.Png";
                BtnFav.Text = "Like";
                

            
        

所以我知道如果我做对了,我应该能够操作 Button 和 Image,如果它们在 ListView 内,并获得与填充列表的类别相对应的行。 像这样:

 <ListView
    x:Name="CategoryList" 
          SelectionMode="None"
          ItemsSource="Binding FavCategories">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>

      <Label Grid.Column="0" Text="Binding ., Converterconverters:ToUpperConverter"></Label>
      <Image x:Name="ImgFav"  
 Grid.Column="2" 
 Source="Binding IsFav"></Image>

 <Button x:Name="BtnFav" 
  Grid.Column="3" 
  Text="Binding FavState" 
  Clicked="BtnFav_Clicked"></Button>
     </ViewCell>

        </DataTemplate>
    </ListView.ItemTemplate>

</ListView>

但导致我的 x 按钮和图像名称在当前上下文中不存在。 有没有人有什么智慧可以帮助我克服这个障碍?

提前致谢!

【问题讨论】:

您不能按名称访问模板中的项目。模板中的项目是在运行时动态生成的 - 您应该使用数据绑定来填充它们。 第二,您不能将模板中的项目分配给网格行/列,因为 ListView 包含在 Grid 中,模板中的项目将包含在 ListView 中。您可以在 ViewCell 中放置一个 Grid,然后将模板项放置在该 Grid 中。 @Jason Yea 抱歉忘记调整那部分,这就是我的意思是我尝试将网格放在 ViewCell 中。我将再次尝试数据绑定,遗憾的是我还没有完全掌握它的正确使用方法,但我唯一的线索是,这是正确的方法。 您将 ListView 绑定到 List&lt;string&gt;。而是将其绑定到 List&lt;FavCategoryModel&gt;,然后将模板中的项目绑定到该模型上的不同属性。 检查 Bindings and Collections 或从模板项目开始并检查绑定以获取列表和详细信息。 【参考方案1】:

看看MVVM,你会更清楚的了解设计。使用绑定 ViewMode 时,不建议我们直接处理 Control。另外,如果使用DataTemplate,我们也不会得到x:Name的控制权。

不必担心如何获取控件的x:Name,只需关注你要实现的功能即可。它会使用MVVM来实现你想要的功能。

例如,我的 Xaml 代码如下:

<ListView x:Name="MyListView"
            HasUnevenRows="True"
            RowHeight="150"
            CachingStrategy="RecycleElement"
            ItemSelected="MyListView_ItemSelected"
            ItemsSource="Binding myItems"
            IsVisible="True">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                    <StackLayout Orientation="Horizontal"
                                        VerticalOptions="Center">
                            <Label Text="Hello World"
                                    HorizontalOptions="StartAndExpand"></Label>
                            <Label Text="Binding Address"
                                    HorizontalOptions="CenterAndExpand"></Label>
                            <Label Text="Binding eMail"
                                    HorizontalOptions="CenterAndExpand"></Label>
                            
                </StackLayout>
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

然后我将编写如下代码以显示我的需求:

public PageListView()

    InitializeComponent();

    var myItems = new List<Contacts>();
    myItems.Add(new Contacts() Address="1",eMail="1" );
    myItems.Add(new Contacts()  Address = "2", eMail = "2" );
    myItems.Add(new Contacts()  Address = "3", eMail = "3" );
    myItems.Add(new Contacts()  Address = "4", eMail = "4" );
    myItems.Add(new Contacts()  Address = "5", eMail = "5" );

    this.BindingContext = this;
   

Contacts.cs

public class Contacts

    public string Address  get; set; 
    public string eMail  get; set; 

效果:

====================================更新=========== ====================

如果需要默认值,你define a fallback value。

<Label Text="Binding Address, FallbackValue='Address unknown'"
       ... />

并从一个rest api设置ItemSource,这里是the sample。

protected async override void OnAppearing ()

    base.OnAppearing ();

    listView.ItemsSource = await App.TodoManager.GetTasksAsync ();

【讨论】:

已经查看了 MVVM 以及 microsoft 提供的数据绑定文档,但遗憾的是没有关于同一 ViewCell 中控件的不同数据绑定的示例,这些示例仅显示 Xaml 而不是后面的代码。我可能应该提到该列表是从一个 Restful API 填充的,我从 Get 调用中获取数据并放入列表中的相应列,同时还在启动时为其他列添加一些默认值 @Gabbelino Okey,你可以看看this sample,调用rest api在ListView中显示数据。区别在于ItemsSource的数据。如果你需要一个默认值,你可以定义一个fallback value。 @Gabbelino 我已经更新了答案,如果回复有帮助,请不要忘记接受它作为答案(点击该答案左上角的✔)并投票,它将帮助其他有类似问题的人。

以上是关于如何在 ListView x:name 内的 Views 中访问 x:name?是不是可以设置不同形式的用户输入?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 ListView 内的复选框中获取位置

如何将焦点设置到 ListView 委托内的 TextField?

堆栈内的水平Listview:水平视口被赋予无限宽度

带有 DrawerLayout 的 ScrollView 内的 ListView

WPF - 如何在 ListView 中居中列数据?

带有 BaseAdapter 的 Android ListView 内的 ImageButton