XAML 在我滑动屏幕之前不显示ListView

mrzz3bfm  于 2022-12-07  发布在  其他
关注(0)|答案(1)|浏览(121)

我尝试在我的.NET MAUI应用程序中实现StateContainer by Patrick McCurley。当ListView第一次显示时,它工作正常。但是当状态再次改变时,ListView不显示,直到我滑动屏幕。
当我将任何视图元素(标签、按钮等)添加到包含ListView的视图时,该视图元素不会显示。但是,当我将StateContainer与任何其他视图元素一起移动到网格时,ListView会正确显示。如果网格不包含除StateContainer之外的其他元素,则ListView不会正确显示。
我不知道这里有什么问题。网格和其他视图元素对我来说不是一个解决方案,因为我的页面不应该包含任何其他元素,除了状态容器。
下面的示例重现了该问题:
我很抱歉有很多代码:)我不知道问题可能出在哪里。
States.cs

public enum States
{
    Loading, 
    Success
}

StateCondition.cs

[ContentProperty("Content")]
public class StateCondition : View
{
    public object State { get; set; }
    public View Content { get; set; }
}

StateContainer.cs

[ContentProperty("Conditions")]
public class StateContainer : ContentView
{
    public List<StateCondition> Conditions { get; set; } = new();

    public static readonly BindableProperty StateProperty = 
        BindableProperty.Create(nameof(State), typeof(object), typeof(StateContainer), null, BindingMode.Default, null, StateChanged);

    private static void StateChanged(BindableObject bindable, object oldValue, object newValue)
    {
        var parent = bindable as StateContainer;
        if (parent != null)
            parent.ChooseStateProperty(newValue);
    }

    public object State
    {
        get { return GetValue(StateProperty); }
        set { SetValue(StateProperty, value); }
    }

    private void ChooseStateProperty(object newValue)
    {
        if (Conditions == null && Conditions?.Count == 0) return;

        var stateCondition = Conditions
            .FirstOrDefault(condition =>
                condition.State != null &&
                condition.State.ToString().Equals(newValue.ToString()));

        if (stateCondition == null) return;

        Content = stateCondition.Content;
    }
}

MainPage.xaml

<ContentPage ...>

    <state:StateContainer State="{Binding State}">

        <state:StateCondition State="Loading">
            <StackLayout HorizontalOptions="Center" VerticalOptions="Center">
                <ActivityIndicator IsRunning="True" />
                <Label Text="Updating data..." />
            </StackLayout>
        </state:StateCondition>

        <state:StateCondition State="Success">
            <ListView ItemsSource="{Binding SomeData}">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <ViewCell>
                            <Label Text="{Binding . }" />
                        </ViewCell>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </state:StateCondition>

    </state:StateContainer>

</ContentPage>

MainPage.xaml.cs

public partial class MainPage : ContentPage
{
    private States _state;
    private int[] _someData;

    public MainPage()
    {
        InitializeComponent();
        this.BindingContext = this;

        SomeData = new[] { 1, 2, 3, 4, 5 };
        State = States.Success;

        // it can be executed from outside the page
        _ = Task.Run(ExecuteSomeWorkAsync);
    }

    public States State
    {
        get => _state;
        private set
        {
            if (_state != value)
            {
                _state = value;
                OnPropertyChanged();
            }
        }
    }
    public int[] SomeData
    {
        get => _someData;
        private set
        {
            if (_someData != value)
            {
                _someData = value;
                OnPropertyChanged();
            }
        }
    }

    public async Task ExecuteSomeWorkAsync()
    {
        await Task.Delay(2000);

        State = States.Loading;

        await Task.Delay(2000);

        // generate new data for displaying
        Random rnd = new();
        var data = Enumerable.Range(0, 5).Select(n => rnd.Next(0, 5)).ToArray();

        SomeData = data;
        State = States.Success;
    }
}
chhkpiq4

chhkpiq41#

我怀疑Content = stateCondition.Content;无法正确更新显示。
另一种解决方案是定义public class StateContainer : StackLayout,并在每个子项上使用IsVisible="True"/"False",以控制显示的内容。所有stateConditions仍然是stateContainer的子项,但一次只能显示一个。

相关问题