AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / coding / Perguntas / 77251032
Accepted
Bob
Bob
Asked: 2023-10-08 02:32:27 +0800 CST2023-10-08 02:32:27 +0800 CST 2023-10-08 02:32:27 +0800 CST

.NET Maui CollectionView, como exibir o valor somente se o valor existir

  • 772

Gostaria de exibir as propriedades em uma lista de objetos, mas se as propriedades não tiverem nenhum valor, gostaria não apenas de deixá-las em branco, mas também de fazer com que a linha inteira não exista (isso é fundamental).

Aqui está o que quero dizer: digamos que eu tenha um objeto com quatro valores de string:

object person:
string firstname
string lastname
string favoriteMovie
string favoriteBook

Na verdade, tenho uma lista deles: ObservableList<Person>. Quero exibir Person as propriedades de cada Pessoa usando CollectionView, somente se a propriedade não tiver um valor, quero ignorá-la.

Pode ser algo assim:
insira a descrição da imagem aqui

O código XAML seria mais ou menos assim:

<CollectionView ItemsSource={Binding People}>
   <CollectionView.ItemTemplate>
      <DataTemplate x:DataType="model:Person">
           <Frame>
               <Grid>
                   <Label Text="{Binding Name}"/>
                   <Label Text="{Binding FavoriteMovie}"/>
                   <Label Text="{Binding FavoriteBook}"/>
               ...
            ...
        ...
      ...
  </CollectionView>

Como faço isso?

NOTA: estou usando o padrão MVVM e gostaria de fazer isso principalmente em XAML, se possível.

maui
  • 2 2 respostas
  • 32 Views

2 respostas

  • Voted
  1. Best Answer
    FreakyAli
    2023-10-08T03:05:43+08:002023-10-08T03:05:43+08:00

    Você precisará de um conversor que converta strings vazias ou nulas em booleanos e, em seguida, precisará atribuí-lo à visibilidade do seu item para que algo como o abaixo funcione,

    /// <summary>
    /// Inherit this for one-way converters to avoid unnecessary extra methods in each converter
    /// </summary>
    public abstract class BaseOneWayValueConverter : IValueConverter
    {
        public abstract object Convert(object value, Type targetType, object parameter, CultureInfo culture);
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotSupportedException($"{GetType().Name} is a one-way converter");
        }
    }
    
    public class StringIsNullToBoolConverter : BaseOneWayValueConverter
    {
        public override object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return value is not string text || !string.IsNullOrWhiteSpace(text);
        }
    }
    

    E então use-o em seu Label conforme mostrado abaixo:

    <ContentPage
    .
    .
    .
    .
    xmlns:converters=*converter-namepsace-here* 
    >
    <ContentPage.Resources>
       <StringIsNullToBoolConverter x:Key="StringIsNullToBoolConverter"/>
    </ContentPage.Resources>
    

    Em seguida, use-o em seus respectivos rótulos:

    <Label Text="{Binding Name}" IsVisible="{Binding Name,Converter={StaticResource StringIsNullToBoolConverter}}"/>
    
    • 0
  2. Peter Wessberg
    2023-10-08T04:39:11+08:002023-10-08T04:39:11+08:00

    Aqui está uma maneira de fazer isso. Primeiro fazemos o Model que é responsivo usando o INotifyPropertyChangede a PropertyChangedEventHandler, aqui também colocamos o booleano para usar se vamos apresentar a linha ou não.

    public class Person : INotifyPropertyChanged
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string FavoriteMovie { get; set; }
        public string FavoriteBook { get; set; }
    
        public string DisplayName => FirstName + " " + LastName;
    
        public bool HasFavoriteMovie => !string.IsNullOrEmpty(FavoriteMovie);
        public bool HasFavoriteBook => !string.IsNullOrEmpty(FavoriteBook);
    
        public event PropertyChangedEventHandler PropertyChanged;
    }
    

    O código xaml para imitar o layout da sua imagem. No rótulo/grade vinculamos IsVisibleao valor booleano do modelo.

    <ContentPage.Resources>
        <Style x:Key="LabelStyle" TargetType="Label">
            <Setter Property="TextColor" Value="{StaticResource Blue100Accent}" />
            <Setter Property="FontSize" Value="18" />
            <Setter Property="LineHeight" Value="1.2" />
        </Style>
        <Style x:Key="TitleLabelStyle" TargetType="Label">
            <Setter Property="TextColor" Value="{StaticResource Primary}" />
            <Setter Property="FontSize" Value="28" />
            <Setter Property="TextTransform" Value="Uppercase" />
            <Setter Property="FontAttributes" Value="Bold" />
            <Setter Property="HorizontalOptions" Value="Center" />
            <Setter Property="LineHeight" Value="1.2" />
        </Style>
        <DataTemplate x:Key="PeopleTemplate">
            <Border
                Margin="20,10,10,10"
                BackgroundColor="{StaticResource LightBackgroundColor}"
                Stroke="Gray"
                StrokeThickness="2">
                <Border.StrokeShape>
                    <RoundRectangle CornerRadius="10" />
                </Border.StrokeShape>
                <Border.GestureRecognizers>
                    <TapGestureRecognizer Command="{Binding Source={RelativeSource AncestorType={x:Type viewmodels:PeopleViewModel}}, Path=PersonClickedCommand}" CommandParameter="{Binding .}" />
                </Border.GestureRecognizers>
                <Grid Padding="50,10,10,10">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="Auto" />
                    </Grid.RowDefinitions>
                    <Label
                        Grid.Row="0"
                        Style="{StaticResource LabelStyle}"
                        Text="{Binding DisplayName}" />
                    <Label
                        Grid.Row="1"
                        IsVisible="{Binding HasFavoriteMovie}"
                        Style="{StaticResource LabelStyle}"
                        Text="{Binding FavoriteMovie}" />
                    <Label
                        Grid.Row="2"
                        IsVisible="{Binding HasFavoriteBook}"
                        Style="{StaticResource LabelStyle}"
                        Text="{Binding FavoriteBook}" />
                </Grid>
            </Border>
        </DataTemplate>
    </ContentPage.Resources>
    <VerticalStackLayout HorizontalOptions="Center" VerticalOptions="Center">
        <Label Style="{StaticResource TitleLabelStyle}" Text="People" />
        <CollectionView
            x:Name="PeopleCollection"
            ItemSizingStrategy="MeasureFirstItem"
            ItemTemplate="{StaticResource PeopleTemplate}"
            ItemsSource="{Binding People}">
            <CollectionView.ItemsLayout>
                <LinearItemsLayout Orientation="Vertical" />
            </CollectionView.ItemsLayout>
        </CollectionView>
        <Button
            Command="{Binding AddPersonCommand}"
            Text="Add Person"
            WidthRequest="200" />
    </VerticalStackLayout>
    

    E finalmente no seu ViewModel você tem

    public partial class PeopleViewModel : ObservableObject
    {
        public ObservableCollection<Person> People { get; set; }
    
        public PeopleViewModel()
        {
            People = new ObservableCollection<Person>
            {
                new Person { FirstName = "John", LastName = "Doe", FavoriteMovie = "Inception", FavoriteBook = "1984" },
                new Person { FirstName = "Jane", LastName = "Doe", FavoriteMovie = "Avatar" },
                new Person { FirstName = "Michael", LastName = "Brown" }
            };
        }
    
        [RelayCommand]
        private async Task PersonClicked(Person person)
        {
            var navigationParameter = new Dictionary<string, object>
                {
                    { "Person", person }
                };
            await Shell.Current.GoToAsync($"{nameof(PersonPage)}", navigationParameter);
        }
    
        [RelayCommand]
        private void AddPerson()
        {
            People.Add(new Person { FirstName = "Emily", LastName = "Smith", FavoriteBook = "To Kill a Mockingbird" });
        }
    }
    

    Isto é o que parece. Espero que seja isso que você deseja.

    insira a descrição da imagem aqui

    • 0

relate perguntas

  • ScrollView não funciona em ItemTemplte em CollectionView no Android

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    destaque o código em HTML usando <font color="#xxx">

    • 2 respostas
  • Marko Smith

    Por que a resolução de sobrecarga prefere std::nullptr_t a uma classe ao passar {}?

    • 1 respostas
  • Marko Smith

    Você pode usar uma lista de inicialização com chaves como argumento de modelo (padrão)?

    • 2 respostas
  • Marko Smith

    Por que as compreensões de lista criam uma função internamente?

    • 1 respostas
  • Marko Smith

    Estou tentando fazer o jogo pacman usando apenas o módulo Turtle Random e Math

    • 1 respostas
  • Marko Smith

    java.lang.NoSuchMethodError: 'void org.openqa.selenium.remote.http.ClientConfig.<init>(java.net.URI, java.time.Duration, java.time.Duratio

    • 3 respostas
  • Marko Smith

    Por que 'char -> int' é promoção, mas 'char -> short' é conversão (mas não promoção)?

    • 4 respostas
  • Marko Smith

    Por que o construtor de uma variável global não é chamado em uma biblioteca?

    • 1 respostas
  • Marko Smith

    Comportamento inconsistente de std::common_reference_with em tuplas. Qual é correto?

    • 1 respostas
  • Marko Smith

    Somente operações bit a bit para std::byte em C++ 17?

    • 1 respostas
  • Martin Hope
    fbrereto Por que a resolução de sobrecarga prefere std::nullptr_t a uma classe ao passar {}? 2023-12-21 00:31:04 +0800 CST
  • Martin Hope
    比尔盖子 Você pode usar uma lista de inicialização com chaves como argumento de modelo (padrão)? 2023-12-17 10:02:06 +0800 CST
  • Martin Hope
    Amir reza Riahi Por que as compreensões de lista criam uma função internamente? 2023-11-16 20:53:19 +0800 CST
  • Martin Hope
    Michael A formato fmt %H:%M:%S sem decimais 2023-11-11 01:13:05 +0800 CST
  • Martin Hope
    God I Hate Python std::views::filter do C++20 não filtrando a visualização corretamente 2023-08-27 18:40:35 +0800 CST
  • Martin Hope
    LiDa Cute Por que 'char -> int' é promoção, mas 'char -> short' é conversão (mas não promoção)? 2023-08-24 20:46:59 +0800 CST
  • Martin Hope
    jabaa Por que o construtor de uma variável global não é chamado em uma biblioteca? 2023-08-18 07:15:20 +0800 CST
  • Martin Hope
    Panagiotis Syskakis Comportamento inconsistente de std::common_reference_with em tuplas. Qual é correto? 2023-08-17 21:24:06 +0800 CST
  • Martin Hope
    Alex Guteniev Por que os compiladores perdem a vetorização aqui? 2023-08-17 18:58:07 +0800 CST
  • Martin Hope
    wimalopaan Somente operações bit a bit para std::byte em C++ 17? 2023-08-17 17:13:58 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve