2016-03-01 18 views
6

Tôi đang cố gắng tạo một ListView với các hàng có thể nhấp. Khi bạn bấm vào một hàng nó sẽ đặt một lớp con để hiển thị đúng. Điều này hoạt động tốt trong android, nhưng không phải trong ios. Có lẽ tôi đang làm điều đó một cách sai lầm. Tôi vẫn là một người mới bắt đầu, bất kỳ ý tưởng làm thế nào để sửa lỗi này hay cách tiếp cận nào tốt hơn? Vấn đề là nó mở ra trên ios để thay đổi mức hiển thị, nhưng nó không cập nhật chiều cao của ô. Các tế bào cập nhật off-screen ví dụ nếu bạn di chuyển lên cho đến khi bạn không thể nhìn thấy các tế bào đã mở nữa và sau đó di chuyển xuống. Bạn sẽ thấy nó đã cập nhật chiều cao.Chế độ xem danh sách không được cập nhật khi isVisible được đặt thành true

Tôi đã thử sử dụng trình kết xuất tùy chỉnh nhưng tôi không biết bắt đầu từ đâu.

Đây là XAML của tôi:

<?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> 

Đây là một ví dụ về cách thức hoạt động trên Android và làm thế nào tôi muốn nó hoạt động trên ios. Listview example

+0

Các bạn đã thử gọi ForceLayout() trên Layout bạn – StarterPack

Trả lời

5

Tôi đã sao chép sự cố của bạn trong một thử nghiệm nhỏ. Tôi thích thực hiện thay đổi bố cục thông qua ràng buộc dữ liệu, thay vì mã phía sau.

Hãy bắt đầu với các Template:

<?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> 

Các DataTemplate là về cơ bản giống nhau, nhưng:

  • các StackLayout has no Bấm-Listener
  • các Visbility của StackLayout là được liên kết với IsSelected (IsVisible="{Binding IsSelected}")
  • các SelectedItem của ListView là ràng buộc để SelectedItem của ViewModel của chúng tôi

chúng tôi Trang chỉ đặt ViewModel như DataContext

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

Các ViewModel

  • thực hiện INotifyPropertyChanged thông báo cho xem về thay đổi dữ liệu
  • thêm một số mặt hàng giả vào bộ sưu tập Categories của chúng tôi
  • có một tài sản mà cập nhật IsSelected tài sản của Categories SelectedItem
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()); 
    } 
} 

Cuối cùng nhưng không kém, nhưng quan trọng nhất, bạn cần một nhỏ trình kết xuất tùy chỉnh ghi đè lên giá trị mặc định. Chúng tôi gọi số ReloadData() nếu số SelectedItem đã thay đổi.

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

quả

List View with dynamic cells

+0

này có thể được thực hiện chỉ với tải lại hàng bạn nhấp? – Jim

+0

Có thể. Nhưng 'ReloadData' là một phương pháp thông thường trong iOS để báo hiệu thay đổi dữ liệu cho' UITableView'. Đó là lý do tại sao tôi đã chọn cách tiếp cận này. Vì vậy, tôi cho rằng nó được tối ưu hóa bằng cách nào đó, nếu hiệu suất là mối quan tâm của bạn. –

Các vấn đề liên quan