2016-03-01 83 views
6

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

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

这是我的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工作。 Listview example

+0

您是否尝试过在你的布局 – StarterPack

回答

5

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

让我们先从模板

<?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中是basicaly相同,但:

  • StackLayout没有点击,监听
  • 的StackLayout的Visbility是绑定到IsSelectedIsVisible="{Binding IsSelected}"
  • ListViewSelectedItem必将对我国视图模型的SelectedItem

我们仅设置ViewModelDataContext

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

视图模型

  • 实现INotifyPropertyChanged通知查看数据更改
  • 增加了一些虚拟物品我们Categories收藏
  • SelectedItem属性,更新类别的IsSelected财产
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已更改,我们称​​。

[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()); 
      } 
     } 
    } 
} 

结果

List View with dynamic cells

+0

调用ForceLayout()可以这样只有重装你点击该行办? – Jim

+0

也许吧。但是'ReloadData'是iOS中常用的方法,可以将数据更改发送到'UITableView'。这就是我选择这种方法的原因。所以我假设它是以某种方式进行优化的,如果性能是你关心的。 –

相关问题