首页 > 解决方案 > 点击时更改 ListView 项目的 RowDefinition

问题描述

我正在尝试实现的是一个消息聊天气泡,您可以在其中点击控件/消息,消息将展开,显示日期的详细信息以及下面的已查看/已发送状态。对于发送方和接收方的不同控件,我确实有一个 DataTemplate 选择器。

我的问题是更改 ListView 中消息的高度。我尝试将 RowDefinition 绑定到我的 Message 类(保存有关消息的信息的类)中的任何 Height 变量。虽然高度更新了,但它并没有反映在 ListView 上。我已经在互联网上搜索了现有的聊天 UI 模板,但我认为其中大部分都是付费的。因此,我正在尝试遵循Change WPF DataTemplate for ListBox item if selected。但是对于 Xamarin,没有 ListBoxItem,因为只有一个 ListView。

另外,我正在开发 Android 和 iOS。一个解决这个问题的跨平台示例将不胜感激。以下是我的部分代码。

数据模板.cs

class MessageTemplateSelector : DataTemplateSelector
{
    public MessageTemplateSelector()
    {
        ReceiverDataTemplate = new DataTemplate(typeof(MessageReceiver));
        SenderDataTemplate = new DataTemplate(typeof(MessageSender));
    }

    protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
    {
        var message = item as Message;
        if (message == null)
            return null;
        return message.isSender ? ReceiverDataTemplate : SenderDataTemplate;
    }

    private readonly DataTemplate ReceiverDataTemplate;
    private readonly DataTemplate SenderDataTemplate;
}

MessageSender.xaml

<?xml version="1.0" encoding="UTF-8"?>
<ViewCell xmlns="http://xamarin.com/schemas/2014/forms" 
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    x:Class="Project.layout.MessageSender">
    <ViewCell.View>
        <Grid HorizontalOptions="EndAndExpand">
            <Grid.RowDefinitions>
                <RowDefinition Height="{Binding Path=Height}"/>
                <RowDefinition Height="*" />
                <RowDefinition Height="{Binding Path=Height}" />
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="75" />
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="15" />
            </Grid.ColumnDefinitions>
            <Label Text="{Binding Path=timestamp}" Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="3" HorizontalTextAlignment="Center" HorizontalOptions="Center" VerticalOptions="Center" IsVisible="{Binding Path=Selected}"/>
            <Frame Padding="0" CornerRadius="20" Grid.Column="1" Grid.Row="1" HorizontalOptions="EndAndExpand" >
                <Grid BackgroundColor="White" VerticalOptions="FillAndExpand">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*" />
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="*" />
                    </Grid.RowDefinitions>
                    <Label Text="{Binding Path=text}" VerticalOptions="FillAndExpand" Margin="15,10"/>
                </Grid>
            </Frame>
            <Label Text="Seen" Grid.Column="1" Grid.Row="2" HorizontalOptions="EndAndExpand" IsVisible="{Binding Path=Selected}"/>
        </Grid>
  </ViewCell.View>
</ViewCell>

消息.cs

class Message
{
        public bool isSender { get; set; }
        public sbyte status { get; set; }
        public string text { get; set; }
        public string timestamp { get; set; }
        public Message(bool isSender, sbyte status, string text, string timestamp)
        {
            this.isSender = isSender;
            this.status = status;
            this.text = text;
            this.timestamp = timestamp;
        }
        public sbyte height = 0;
        public sbyte Height { get { return height; }  set { height = value; } }
        bool selected = false;
        public bool Selected
        {
            get { return selected; }
            set { selected = value;if (value) { Height = 25; } else { Height = 0; } }
        }
    }

显示主页.xaml

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:Project.model"
             x:Class="Project.MainPage">
    <ContentPage.Resources>
        <ResourceDictionary>
            <local:MessageTemplateSelector x:Key="MessageTemplateSelector"></local:MessageTemplateSelector>
        </ResourceDictionary>
    </ContentPage.Resources>
    <StackLayout>
        <ListView x:Name="conversation"
                  ItemTemplate="{StaticResource MessageTemplateSelector}"
                    ItemsSource="{Binding Message}"
                    HasUnevenRows="True"
                    SeparatorVisibility="None"
                    RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToParent,Property=Height,Factor=1,Constant=0}"
                  IsPullToRefreshEnabled="true"
                  ItemTapped="Conversation_ItemTapped"
                  Refreshing="Conversation_Refreshing">
        </ListView>
</ContentPage>

主页.cs

private void Conversation_ItemTapped(object sender, ItemTappedEventArgs e)
{
    if (e.Item == null) return;
    Message selectedItem = (Message)e.Item;
    Log.Debug("ItemTap","Height before:" + selectedItem.Height);
    if (selectedItem.Selected) { ((ListView)sender).SelectedItem = null; selectedItem.Selected = false; }
    else { selectedItem.Selected = true; }
    Log.Debug("ItemTap", "Height after:" + selectedItem.Height);
}

这是我的日志的屏幕截图,它出现在我的 ListView 的 ItemTapped 事件中。如您所见,高度会更新,但不会反映在 ListView 上。

证明在项目点击时高度更新

标签: c#xamllistviewxamarin

解决方案


推荐阅读