Динамически скрывая элемент ListView Xamarin Forms и устанавливая высоту невидимого элемента в 0, не работает на iOS - PullRequest
0 голосов
/ 17 февраля 2020

В ListView Xamarin Forms StackLayout помещается в ViewCell. Следующий триггер используется для установки высоты и поля StackLayout равным 0, чтобы в ListView не было пропуска.

<StackLayout.Triggers>
    <Trigger TargetType="StackLayout" Property="IsVisible" Value="False">
        <Setter Property="HeightRequest" Value="0" />
        <Setter Property="Margin" Value="0" />
    </Trigger>
</StackLayout.Triggers>

Код отлично работает на Android. Но на iOS все еще есть пробелы.

Обычно вызов ViewCell.ForceUpdateSize для события касания может помочь решить такую ​​проблему. Но нам нужно сделать это грамматически. Поэтому я попытался создать CustomViewCell, но это не помогло.

public class CustomViewCell : ViewCell
{
    protected override void OnBindingContextChanged()
    {
        base.OnBindingContextChanged();

        var viewModel = (tecommobile.ViewModels.Input)BindingContext;
        viewModel.PropertyChanged += (sender, e) =>
        {
            if (Device.RuntimePlatform == Device.iOS)
            {
                if (e.PropertyName == "IsVisible")
                {
                    //ForceUpdateSize(); crashes, the possible cause could be the height of the StackLayout is already set to 0. The test shows that the tapped event doesn't fire if the height is 0.
                }
            }
        };
    }
}

Пожалуйста, посоветуйте решение или любой обходной путь. Спасибо.

1 Ответ

0 голосов
/ 17 февраля 2020

Мы должны использовать TriggerAction , чтобы изменить это значение, и сказать ViewCell , чтобы обновить его размер.

public class ForceUpdateSizeTriggerAction : TriggerAction<VisualElement>
{
    public double HeighRequest { set; get; }  // you could set it as bindable property if you want to binding its value in runtime

    public Thickness CustomMargin { set; get; }

    public ForceUpdateSizeTriggerAction() : base()
    {

    }
    protected override void Invoke(VisualElement sender)
    {

        var parent = sender.Parent;
        while (parent != null && !(parent is ViewCell))
        {
            parent = parent.Parent;
        }
        if (parent is ViewCell cell)
        {
            Device.BeginInvokeOnMainThread(() =>
            {
                var view = sender as View;
                view.HeightRequest = HeighRequest;
                view.Margin = CustomMargin;
                cell.ForceUpdateSize();
            });
        }
    }
}

в xaml

<StackLayout.Style>
   <Style TargetType="StackLayout">
       <Setter Property="HeightRequest" Value="xxx"/> //default height
          <Style.Triggers>
            <DataTrigger TargetType="StackLayout" Binding="{Binding xxx}"  Value="False">  /// xxx here is the property which binding to the IsVisible of stacklayout
                   <DataTrigger.EnterActions>
                        <local:ForceUpdateSizeTriggerAction HeighRequest="0.01" CustomMargin="0"/>
                   </DataTrigger.EnterActions>

                   <DataTrigger.ExitActions>
                        <local:ForceUpdateSizeTriggerAction HeighRequest="xxx" CustomMargin="xxx"/> // set the default value of height and margin here
                   </DataTrigger.ExitActions>
          </DataTrigger>
       </Style.Triggers>
   </Style>
</StackLayout.Style>

И не забудьте установить HasUnevenRows="True" списка.

...