Xamarin表单框架未随内容扩展

时间:2019-03-04 06:38:54

标签: user-interface mvvm data-binding xamarin.forms

我是Xamarin Forms的新手,我遇到了第一个挑战。我想在Listview中的Stacklayout周围放置一个Frame。当用户在列表视图中选择一个项目时,我希望一些控件出现。在没有框架的情况下,此方法可以正常工作,但是当控件出现时,框架不会展开。我该如何改变或避免这种行为? 下面的代码。

XAML:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         xmlns:local="clr-namespace:MVVMTest"
         x:Class="MVVMTest.MainPage">
<StackLayout>
    <ListView HasUnevenRows="True" SelectedItem="{Binding SelectedViewItem, Mode=TwoWay}" ItemsSource="{Binding Items}" >
        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <Frame BackgroundColor="White" BorderColor="Black">
                        <StackLayout>
                            <Label Text="{Binding Name}"></Label>
                            <Entry Text="{Binding Details}" IsVisible="{Binding ShowDetails}"></Entry>
                        </StackLayout>
                    </Frame>
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</StackLayout>

XAML.cs

namespace MVVMTest
{
    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            BindingContext = new ViewModel()
            {
                Items = new List<ViewModelItem>()
                {
                    new ViewModelItem()
                    {
                        Name = "Test",
                        Details = "details"
                    },
                    new ViewModelItem()
                    {
                        Name = "Test2",
                        Details = "details2"
                    }
                }
            };
            InitializeComponent();
        }
    }
}

型号:

namespace MVVMTest
{
    public class ViewModel : INotifyPropertyChanged
    {
        private ViewModelItem _selectedViewItem;
        private List<ViewModelItem> _items;

        public event PropertyChangedEventHandler PropertyChanged;
        void OnPropertyChanged([CallerMemberName] string propertyName = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        public ViewModelItem SelectedViewItem
        {
            get
            {
                return _selectedViewItem;
            }
            set
            {
                _selectedViewItem = value;
                OnPropertyChanged();
                if (value != null)
                {
                    value.ShowDetails = !value.ShowDetails;
                    SelectedViewItem = null;
                }
            }
        }

        public List<ViewModelItem> Items
        {
            get
            {
                return _items;
            }
            set
            {
                _items = value;
                OnPropertyChanged();
            }
        }

        public ViewModel()
        {

        }
    }

    public class ViewModelItem : INotifyPropertyChanged
    {
        private bool _showDetails;
        private string _details;
        private string _name;

        public event PropertyChangedEventHandler PropertyChanged;
        void OnPropertyChanged([CallerMemberName] string propertyName = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        public string Name
        {
            get
            {
                return _name;
            }
            set
            {
                _name = value;
                OnPropertyChanged();
            }
        }

        public bool ShowDetails
        {
            get
            {
                return _showDetails;
            }
            set
            {
                _showDetails = value;
                OnPropertyChanged();
            }
        }

        public string Details
        {
            get
            {
                return _details;
            }
            set
            {
                _details = value;
                OnPropertyChanged();
            }
        }
    }
}

1 个答案:

答案 0 :(得分:0)

我最终使用PropertyChanged事件来响应ListView的显示或隐藏。在事件处理程序中,我设置了Frame的HeightRequest,这迫使它自行调整大小。

替代解决方案/帮助可以在这里找到:

http://ws.server.com.br/service/inventory/index.php/compliance/search

XAML:

<StackLayout>
    <ListView HasUnevenRows="True" SelectedItem="{Binding SelectedViewItem, Mode=TwoWay}" ItemsSource="{Binding Items}" >
        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <Frame BackgroundColor="White" BorderColor="Black" Margin="2" Padding="2" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
                        <StackLayout>
                            <Label Text="{Binding Name}"></Label>
                            <ListView HasUnevenRows="True" Margin="2" ItemsSource="{Binding DetailObjects}" IsVisible="{Binding ShowDetails}" PropertyChanged="ListView_PropertyChanged">
                                <ListView.ItemTemplate>
                                    <DataTemplate>
                                        <ViewCell>
                                            <Entry Text="{Binding Details}"></Entry>
                                        </ViewCell>
                                    </DataTemplate>
                                </ListView.ItemTemplate>
                            </ListView>
                        </StackLayout>
                    </Frame>
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</StackLayout>

后面的代码:

public partial class MainPage : ContentPage
{
    public MainPage()
    {
        BindingContext = new ViewModel()
        {
            Items = new List<ViewModelItem>()
            {
                new ViewModelItem()
                {
                    Name = "Test",
                    DetailObjects = new List<ViewModelItemDetails>
                    {
                        new ViewModelItemDetails
                        {
                            Details = "details1"
                        },
                        new ViewModelItemDetails
                        {
                            Details = "details2"
                        }
                    }
                },
                new ViewModelItem()
                {
                    Name = "Test2",
                    DetailObjects = new List<ViewModelItemDetails>
                    {
                        new ViewModelItemDetails
                        {
                            Details = "details1"
                        },
                        new ViewModelItemDetails
                        {
                            Details = "details2"
                        }
                    }
                }
            }
        };
        InitializeComponent();
    }

    private void ListView_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        if (!(sender is ListView list)) return;
        if (e.PropertyName == ListView.IsVisibleProperty.PropertyName)
        {
            Element parent = list;
            Frame frame = null;
            while (frame == null && parent != null)
            {
                if (parent is Frame) frame = parent as Frame;
                parent = parent.Parent;
            }

            if (list.IsVisible)
            {
                list.HeightRequest = list.ItemsSource.Cast<ViewModelItemDetails>().Count() * 50;

                if (frame != null) frame.HeightRequest = list.HeightRequest + 50;
            }
            else
            {
                if (frame != null) frame.HeightRequest = 50;
            }
        }
    }
}