Xamarin Forms 动态列表视图

7
我正在尝试在xamarin.forms中创建一个有些复杂的列表。用户应该能够点击列表中的项目,然后它会展开成为更大的东西。更大的项目现在应该显示一些与此视图特别相关的附加UI组件。
我想知道如何解决这个问题。这是关于一个具有动态大小项目的列表视图。单击项目后,该项目将显示与该项目相关的其他视图。这应该在Xamarin.ios和Xamarin.droid中完成,还是建议尝试在xamarin.forms中实现?
我会发布一张图片,它不太好,可能需要放大,但它显示了4个项目。第三个被展开了,因此您可以看到它上面的旋转器和按钮。
一次只能展开一个项目(我可能需要在ViewModel中处理),并且按下另一个项目后,旧项目应该被隐藏。

The list

编辑:

感谢Rohit的帮助,我开始在Xamarin.Forms中实现一个解决方案,但仍然存在一些问题,即行如何展开。请参见下面的图片。为了简单起见,我跳过了旋转器,只使用了一个按钮。扩展的行与其下面的行重叠。第一张图片是点击之前的状态,第二张是点击名为“Two”的项目后的状态。

视图

<?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="simpletest.PlayGroundPage">
    <ContentPage.Content>
        <StackLayout>
            <ListView VerticalOptions="FillAndExpand" HasUnevenRows="True" ItemsSource="{Binding AllItems}" SelectedItem="{Binding MySelectedItem}">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <StackLayout VerticalOptions="FillAndExpand">
                            <StackLayout VerticalOptions="FillAndExpand" Orientation="Horizontal">
                                <Label Text="{Binding MyText}" />
                                <Image Source="{Binding MyImage}" />
                            </StackLayout>
                            <Button Text="button1" IsVisible="{Binding IsExtraControlsVisible}" />  
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

项目
    public class Item : INotifyPropertyChanged
    {


        public Item(string text, string image, int id)
        {
            _myText = text;
            _myImage = image;
            _id = id;
            _isExtraControlsVisible = false;

        }

        private string _myText;
        private string _myImage;
        private bool _isExtraControlsVisible;
        private int _id;

        public event PropertyChangedEventHandler PropertyChanged;

        public int Id { get { return _id; } set { _id = value; } }

        public string MyText
        {
            get { return _myText; }
            set { _myText = value; OnPropertyChanged("MyText"); }
        }
        public string MyImage
        {
            get { return _myImage; }
            set { _myImage = value; OnPropertyChanged("MyImage"); }
        }
        public bool IsExtraControlsVisible
        {
            get { return _isExtraControlsVisible; }
            set { _isExtraControlsVisible = value; OnPropertyChanged("IsExtraControlsVisible"); }
        }

        private void OnPropertyChanged(string property)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(property));
            }
        }
    }

视图模型:

    class PlayGroundViewModel : INotifyPropertyChanged
    {
        private Item _mySelectedItem;



        public PlayGroundViewModel(ObservableCollection<Item> allItems)
        {
            AllItems = allItems;
            _mySelectedItem = allItems.First();
        }
        public ObservableCollection<Item> AllItems { get; set; }

        public Item MySelectedItem
        {
            get { return _mySelectedItem; } //Added a field for this one, mainly for debugging.
            set
            {

                foreach (Item x in AllItems) //Changed to non-linq since it is not a list.
                {
                    x.IsExtraControlsVisible = false;
                }

                if (value != null)
                {
                    foreach (Item x in AllItems)
                    {
                        if (x.Id.Equals(value.Id))
                        {
                            x.IsExtraControlsVisible = true;
                            _mySelectedItem = x;
                        }
                    }
                }

                SetChangedProperty("MySelectedItem");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void SetChangedProperty(string property)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(property));
            }
        }

    }

CodeBehind:

    public partial class PlayGroundPage : ContentPage
    {
        public PlayGroundPage()
        {
            InitializeComponent();
            ObservableCollection<Item> items = new ObservableCollection<Item>();
            items.Add(new Item("One", "", 0));
            items.Add(new Item("Two", "", 1));
            items.Add(new Item("Three", "", 2));
            PlayGroundViewModel weekViewModel = new PlayGroundViewModel(items);
            BindingContext = weekViewModel;
        }
    }

Before clicking on a row

After having clicked


我以前做过这个。如果您正在使用MVVM并且将ItemsSource绑定到ViewModel上的IList,则只需要将Button和Spinner的IsVisible属性绑定到ViewModel上的2个bool属性即可。当用户单击该项时,这应该调用ViewModel上的一个ICommand,并且您可以将这两个IsVisible属性都设置为true。 - Jon
@Mangist,你能展示一下你的代码吗? - Jeremy Thompson
@JeremyThompson 你能先试试我的建议吗? - Jon
我知道这会有效,[SO]的目标是成为编程问题和答案的资源,不得不翻阅评论可能毫无意义。你为什么不想发表答案?如果你不这样做,对我来说并没有任何影响,如果你不这样做,你不会赚取声望,也不会得到回报。更糟糕的是,如果有人按照你的建议发布代码并窃取了你的风头。 - Jeremy Thompson
OP确实问道“我该如何解决这个问题”,所以我指导他朝正确的方向去思考。他并没有要求完整的代码解决方案。Stack Overflow也不是你来找人写代码的地方。如果他不尝试根据别人的指导实现解决方案,他将学不到任何东西,并且会再次提出同样的问题。你真的在寻找OP问题的解决方案吗? - Jon
显示剩余4条评论
1个回答

2
你可以使用XAML、ViewModel和ObservableCollection以以下方式进行实现。
XAML:
<ListView VerticalOption="FillAndExpand" HasUnevenRows="True" 
 ItemsSource="{Binding AllItems}" SelectedItem="{Binding MySelectedItem}" >
 <ListView.ItemTemplate>
   <DataTemplate>
      <ViewCell>
         <StackLayout VerticalOptions="FillAndExpand">
            <StackLayout VerticalOptions="FillAndExpand" Orientation="Horizontal">
               <Label Text="{Binding MyText}" />
               <Image Source="{Binding MyImage}" />
            </StackLayout>
            <Button Text="button" IsVisible="{Binding IsExtraControlsVisible}" />
            <Spinner IsVisible="{Binding IsExtraControlsVisible}" />
         </StackLayout>
      </ViewCell> 
   </DataTemplate>
 </ListView.ItemTemplate>
</ListView>

ViewModel :

public ObservableCollection<Item> AllItems
{
    get { return _allItems; }
    set
    {
        _allItems = value;
        OnPropertyChanged();
     }
}
public Item MySelectedItem
{
    get { return _mySelectedItem; }
    set
    {
        _mySelectedItem = value;
        OnPropertyChanged();

        foreach (var item in AllItems)
        {
            item.IsExtraControlsVisible = false;
        }
        var selectedItem = AllItems.FirstOrDefault(x => x.Equals(value));
        if (selectedItem != null)
        {
            selectedItem.IsExtraControlsVisible = true;
        }
    }
}

Item.cs :

public class Item : INotifyPropertyChanged
{
   private string _myText;
   private string _myImage;
   private bool _isExtraControlsVisible;
   private int _id;

   public int Id { get; set; }
   public string MyText 
   {
       get{ return _myText; } 
       set
       { _myText = value; 
          OnPropertyChanged();
       } 
   }
   public string MyImage
   {
       get{ return _myImage; } 
       set
       {
            _myImage = value; 
            OnPropertyChanged();
       } 
   }
   public bool IsExtraControlsVisible
   {
       get{ return _isExtraControlsVisible; } 
       set
       {
           _isExtraControlsVisible = value;
           OnPropertyChanged();
       } 
   }
}

请在此处查看演示 - XamarinForms_Dynamic_ListView_Item

1
谢谢,但是我没能让它工作。由于该类的限制,我更改了ObservableCollection上的foreach,并只是在VerticalOption中添加了一个小s。还实现了一个MySelectedItem的get。填充了一些项目。当我点击项目并调试时,我看到Items visibleproperty变为true。我还实现了一个以字符串作为参数的OnPropertyChanged,并传递例如“IsExtraControlsVisible”。该行只是不展开。你认为我有什么误解吗?解决方案看起来很好,我很想这样解决它。 - why_vincent
你能把你已经实现的内容添加到问题中吗? - Rohit Vipin Mathews
我现在已经编辑了帖子,并添加了您的代码和我的修改。我是一名Java开发人员,最近开始接触.net,所以可能会违反一些惯例。 - why_vincent
如果它解决了问题,请接受答案,以便将来对其他人有用。 "HasUnevenRow" 属性应该解决您的重叠问题。 - Rohit Vipin Mathews
它仍然有点让我困扰,但我非常感激,当然我会接受它。非常感谢。 - why_vincent
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接