当isVisible设置为true时,Listview未更新 [英] Listview not updated when isVisible is set to true

查看:268
本文介绍了当isVisible设置为true时,Listview未更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用可点击的行制作 ListView 。当您单击某一行时,它会将子堆栈布局设置为可见性为true。这在android中运行良好,但在ios中不行。也许我做错了。我仍然是初学者,任何想法如何解决这个或任何其他更好的方法?
问题是它在ios上打开,因此可见性发生了变化,但它没有更新单元格的高度。例如,如果向上滚动直到无法再看到打开的单元格,然后向下滚动,则单元格会在屏幕外更新。你会看到它已经更新了高度。

I'm trying to make a ListView with clickable rows. When you click on a row it sets a child stacklayout to visibility true. This works fine in android, but not in ios. Maybe I'm doing it the wrong way. I am still a beginner, any idea how to fix this or any other better approach? The problem is that it opens on ios so the visibility changes, but it does not update the height of the cell. The cell updates off-screen for example if you scroll up until you can't see the opened cell anymore and then scroll back down. You'll see it has updated the height.

我尝试使用自定义渲染器,但我不知道从哪里开始。

I tried using a custom renderer, but i have no idea where to start.

这是我的xaml:

<?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="Lisa.Excelsis.Mobile.AssessmentPage" xmlns:local="clr-namespace:Lisa.Excelsis.Mobile;assembly=Lisa.Excelsis.Mobile">
<StackLayout>
    <local:SpecialListView x:Name="CategoryList" 
                ItemsSource = "{Binding Categories}" 
                HasUnevenRows="true" 
                RowHeight="-1" 
                GroupDisplayBinding="{Binding Name}"
                IsGroupingEnabled="true">
        <local:SpecialListView.ItemTemplate>
            <DataTemplate> 
                <ViewCell x:Name="ObservationCell">
                    <ViewCell.View>
                        <StackLayout x:Name="ObservationContainer"
                                     HorizontalOptions="FillAndExpand"
                                     Orientation="Vertical"
                                     VerticalOptions="StartAndExpand"
                                     BackgroundColor="White">   
                            <StackLayout x:Name="Observation"   
                                         HorizontalOptions="FillAndExpand"
                                         VerticalOptions="StartAndExpand"                                        
                                         Padding="15, 10, 10, 10"
                                         BackgroundColor="White">   
                                <StackLayout.GestureRecognizers>
                                    <TapGestureRecognizer Tapped="OpenItem"/>
                                </StackLayout.GestureRecognizers>

                                <Grid HorizontalOptions="FillAndExpand" >
                                    <Grid.RowDefinitions>
                                        <RowDefinition Height="Auto" />     
                                        <RowDefinition Height="Auto" />                 
                                    </Grid.RowDefinitions>

                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="35" />
                                        <ColumnDefinition Width="*" />
                                    </Grid.ColumnDefinitions>

                                    <Label  x:Name="ObservationOrder" 
                                            Text="{Binding Criterion.Order, StringFormat='{0}.'}" 
                                            FontSize="18" 
                                            VerticalOptions="StartAndExpand" 
                                            Grid.Column="0" Grid.Row="0"/>   

                                    <Label  x:Name="ObservationTitle" 
                                            Text="{Binding Criterion.Title}" 
                                            FontSize="18" 
                                            VerticalOptions="StartAndExpand" 
                                            Grid.Column="1" Grid.Row="0"/>

                                </Grid>
                            </StackLayout>
                            <StackLayout x:Name="ObservationButtons"
                                         HorizontalOptions="FillAndExpand"
                                         VerticalOptions="StartAndExpand"
                                         BackgroundColor="White"
                                         IsVisible="false"
                                         Padding="0, 0, 0, 20"
                                         ClassId = "{Binding Id, StringFormat='ObservationButtons_{0}'}">

                                <Grid HorizontalOptions="Center"                                         
                                      Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="2">
                                    <Grid.RowDefinitions>
                                        <RowDefinition Height="Auto" />                 
                                    </Grid.RowDefinitions>

                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="80" />
                                        <ColumnDefinition Width="80" />
                                        <ColumnDefinition Width="10" />
                                        <ColumnDefinition Width="80" />
                                        <ColumnDefinition Width="80" />
                                        <ColumnDefinition Width="80" />
                                        <ColumnDefinition Width="80" />
                                    </Grid.ColumnDefinitions>

                                    <StackLayout Grid.Column="0" Grid.Row="0" >
                                        <Image  Source="yesnobutton0.png" 
                                                HeightRequest="60" WidthRequest="60"
                                                HorizontalOptions="Center"
                                                VerticalOptions="Start"
                                                x:Name="yesImage">   
                                            <Image.GestureRecognizers>
                                                <TapGestureRecognizer Tapped="SetYesImage"/>
                                            </Image.GestureRecognizers>
                                        </Image>

                                        <Label Text="Ja" VerticalOptions="End" HorizontalOptions="Center"/>
                                    </StackLayout>

                                    <StackLayout Grid.Column="1" Grid.Row="0">
                                        <Image  Source="yesnobutton0.png"
                                                HeightRequest="60" WidthRequest="60"
                                                HorizontalOptions="Center"
                                                VerticalOptions="Start"
                                                x:Name="noImage">
                                            <Image.GestureRecognizers>
                                                <TapGestureRecognizer Tapped="SetNoImage"/>
                                            </Image.GestureRecognizers>
                                        </Image>

                                        <Label Text="Nee" VerticalOptions="End" HorizontalOptions="Center"/>
                                    </StackLayout>

                                    <Image  Source="maybenot.png"
                                            HeightRequest="60" WidthRequest="60"
                                            HorizontalOptions="Center"
                                            VerticalOptions="Start"
                                            Grid.Column="3" Grid.Row="0">
                                        <Image.GestureRecognizers>
                                            <TapGestureRecognizer Tapped="SetMark"/>
                                        </Image.GestureRecognizers>
                                    </Image>

                                    <Image  Source="skip.png"
                                            HeightRequest="60" WidthRequest="60"
                                            HorizontalOptions="Center"
                                            VerticalOptions="Start"
                                            Grid.Column="4" Grid.Row="0">
                                        <Image.GestureRecognizers>
                                            <TapGestureRecognizer Tapped="SetMark"/>
                                        </Image.GestureRecognizers>
                                    </Image>

                                    <Image  Source="unclear.png"
                                            HeightRequest="60" WidthRequest="60"
                                            HorizontalOptions="Center"
                                            VerticalOptions="Start"
                                            Grid.Column="5" Grid.Row="0">
                                        <Image.GestureRecognizers>
                                            <TapGestureRecognizer Tapped="SetMark"/>
                                        </Image.GestureRecognizers>
                                    </Image>

                                    <Image  Source="change.png"
                                            HeightRequest="60" WidthRequest="60"
                                            HorizontalOptions="Center"
                                            VerticalOptions="Start"
                                            Grid.Column="6" Grid.Row="0">
                                        <Image.GestureRecognizers>
                                            <TapGestureRecognizer Tapped="SetMark"/>
                                        </Image.GestureRecognizers>
                                    </Image>
                                </Grid>
                            </StackLayout>
                        </StackLayout>
                    </ViewCell.View>
                </ViewCell>
            </DataTemplate>
        </local:SpecialListView.ItemTemplate>
    </local:SpecialListView>
</StackLayout>

这是一个例子它适用于Android以及我希望它如何在ios上工作。

This is an example of how it works on android and how i want it to work on ios.

推荐答案

我在一个小型Testproject中重现了您的问题。我更喜欢通过数据绑定进行布局更改,而不是代码隐藏。

I reproduced your Problem in a small Testproject. I prefer doing layout changes via data binding, instead of code behind.

让我们从模板开始:

<?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="App6.Page1">
  <ListView x:Name="CategoryList"
            BackgroundColor="Gray"
            ItemsSource="{Binding Categories}"
                SelectedItem="{Binding SelectedItem}"
                HasUnevenRows="true"
                RowHeight="-1">
    <ListView.ItemTemplate>
      <DataTemplate>
        <ViewCell x:Name="ObservationCell">
          <ViewCell.View>
            <StackLayout x:Name="Observation"
                        HorizontalOptions="FillAndExpand"
                        VerticalOptions="StartAndExpand"
                        Padding="15, 10, 10, 10"
                        BackgroundColor="White">

              <Label  x:Name="ObservationTitle"
                      Text="{Binding Title}"
                      FontSize="18"
                      TextColor="Black"
                      VerticalOptions="StartAndExpand"/>

              <StackLayout Orientation="Horizontal" IsVisible="{Binding IsSelected}">
                <Image BackgroundColor="Fuchsia" WidthRequest="40" HeightRequest="40"></Image>
                <Image BackgroundColor="Green" WidthRequest="40" HeightRequest="40"></Image>
                <Image BackgroundColor="Yellow" WidthRequest="40" HeightRequest="40"></Image>
                <Image BackgroundColor="Blue" WidthRequest="40" HeightRequest="40"></Image>
                <Image BackgroundColor="Black" WidthRequest="40" HeightRequest="40"></Image>
              </StackLayout>
            </StackLayout>
          </ViewCell.View>
        </ViewCell>
      </DataTemplate>
    </ListView.ItemTemplate>
  </ListView>
</ContentPage>

Datatemplate基本相同,但是:

The Datatemplate is basicaly the same, but:


  • StackLayout 没有Click-Listener

  • StackLayout的可见性绑定到 IsSelected IsVisible ={Binding IsSelected}

  • <$ ListView 的c $ c> SelectedItem 绑定到ViewModel的 SelectedItem

  • the StackLayout has no Click-Listener
  • the Visbility of the StackLayout is bound to IsSelected (IsVisible="{Binding IsSelected}")
  • the SelectedItem of the ListView is bound to SelectedItem of our ViewModel

我们的页面只是将 ViewModel 设置为 DataContext

public partial class Page1 : ContentPage
{
    public Page1()
    {
        InitializeComponent();
        BindingContext = new Page1ViewModel();
    }
}

ViewModel


  • 实现 INotifyPropertyChanged 通知视图有关数据更改

  • 将一些虚拟物品添加到我们的类别集合

  • 有一个 SelectedItem 更新类别的 IsSelected 属性的属性

  • implements INotifyPropertyChanged to notify the view about data changes
  • adds some dummy items to our Categories Collection
  • has a SelectedItem property that updates the IsSelected property of the Categories
class Page1ViewModel : INotifyPropertyChanged
{
    private Category _selectedItem;
    private ObservableCollection<Category> _categories = new ObservableCollection<Category>();
    public event PropertyChangedEventHandler PropertyChanged;

    public ObservableCollection<Category> Categories
    {
        get { return _categories; }
        set
        {
            _categories = value;
            OnPropertyChanged();
        }
    }

    public Category SelectedItem
    {
        get { return _selectedItem; }
        set
        {
            if (_selectedItem == value)
                return;

            if (_selectedItem != null)
            {
                _selectedItem.IsSelected = false;
            }

            _selectedItem = value;
            if (_selectedItem != null)
            {
                _selectedItem.IsSelected = true;
            }
        }
    }

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

    public Page1ViewModel()
    {
        Categories.Add(new Category());
        Categories.Add(new Category());
        Categories.Add(new Category());
        Categories.Add(new Category());
        Categories.Add(new Category());
    }
}

最后但并非最不重要,但最重要的是,你需要一个小的自定义渲染器来覆盖默认渲染器。如果 SelectedItem 已更改,我们调用 ReloadData()

Last, but not least, but most important, you need a tiny custom renderer that overwrites the default one. We call ReloadData() if the SelectedItem has changed.

[assembly: ExportRenderer(typeof(ListView), typeof(MyListViewRenderer))]
namespace App6.iOS.CustomRenderer
{
    public class MyListViewRenderer : ListViewRenderer
    {
        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);
            if (e.PropertyName == ListView.SelectedItemProperty.PropertyName)
            {
                Device.BeginInvokeOnMainThread(() => Control.ReloadData());
            }
        }
    }
}

结果

这篇关于当isVisible设置为true时,Listview未更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆