两个选项卡式子项之间的数据绑定不起作用

时间:2019-07-14 21:02:11

标签: c# android xamarin xamarin.forms

我是Xamarin.Forms开发的新手,我正在尝试构建一个小的Xamarin应用程序来启动。 我的应用程序当前有一个主TabbedPage,其中有两个ContentPages子级。在ListePage上,我有一个带ObservableCollection的ListView,其中OlonaModel是一个具有int Numero和Text字符串的对象。我希望“详细信息”页面从ListePage的列表视图中显示所选OlonaModel的详细信息,但是当我从列表视图中选择一个项目时,“详细信息”页面似乎没有更新为更改。 两个内容页面都绑定到相同的ListPageViewModel。当我从列表视图中选择一个项目时,视图模型会更新,但是更改不会反映在“详细信息”页面上,我真的很困惑。 当设置视图模型的SelectedItem时,如何使Details自身刷新?

主页:

<?xml version="1.0" encoding="utf-8" ?>
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:local="clr-namespace:App.Views"
             xmlns:viewmodels="clr-namespace:App.ViewModels"
             mc:Ignorable="d"
             x:Class="App.MainPage">
    <TabbedPage.Children>
        <local:ListePage/>
        <local:Details/>
    </TabbedPage.Children>
</TabbedPage>

ListePage.xaml(帖子中的ContentPage1):

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             x:Class="App.Views.ListePage"
             Title="Liste">
    <ContentPage.Content>
        <StackLayout>
            <ListView x:Name="ListeMipoitra" ItemSelected="ListeMipoitra_ItemSelected">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <ViewCell>
                            <Grid>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="auto"></ColumnDefinition>
                                </Grid.ColumnDefinitions>
                                <Label Text="{Binding Numero}" Grid.Column="0" FontSize="Medium" FontAttributes="Bold"/>
                            </Grid>
                        </ViewCell>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

ListePage.xaml.cs:

namespace App.Views
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class ListePage : ContentPage
    {
        public static ListePageViewModel viewModel;
        public ListePage()
        {
            InitializeComponent();
            viewModel = new ListePageViewModel();
            this.BindingContext = viewModel;
            ListeMipoitra.ItemsSource = viewModel.listeOlonaVM;
        }

        private void ListeMipoitra_ItemSelected(object sender, SelectedItemChangedEventArgs e)
        {
            viewModel.setSelected((OlonaModel)e.SelectedItem);
        }
    }
}

Details.xaml(帖子中的ContentPage2):

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             x:Class="App.Views.Details"
             Title="Détails">
    <ContentPage.Content>
        <StackLayout>
            <Label Text="{Binding Text}"/>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

Details.xaml.cs:

namespace App.Views
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class Details : ContentPage
    {
        public Details()
        {
            InitializeComponent();
            this.BindingContext = ListePage.viewModel.selected;
        }
    }
}

ListePageViewModel.cs:

注意:我使用的是Fody和PropertyChanged.Fody编织器,因此当属性更改时,会自动调用RaisePropertyChanged()事件

namespace App.ViewModels
{

    public class ListePageViewModel : INotifyPropertyChanged 
    {
        public ObservableCollection<OlonaModel> listeOlonaVM;

        public OlonaModel selected { get; set; }

        public ListePageViewModel()
        {
            listeOlonaVM = new ObservableCollection<OlonaModel>();
            listeOlonaVM = ListeOlona.liste;
        }

        public event PropertyChangedEventHandler PropertyChanged;

        public void setSelected(OlonaModel olona)
        {
            selected = olona;
        }
    }
}

Olona对象的模型:

namespace App.Models
{
    public class OlonaModel
    {
        public int Numero { get; set; }
        public string Text { get; set; }

        public OlonaModel(int num, string text)
        {
            this.Numero = num;
            this.Text= text;
        }
    }
}

用于存储列表模型的ListeOlona.cs:

在应用启动时调用InitializeList()方法。

namespace App.ViewModels
{
    public static class ListeOlona 
    {
        public static ObservableCollection<OlonaModel> liste = new ObservableCollection<OlonaModel>();

        public static void InitializeList()
        {
            liste.Add(new OlonaModel(1,
                "FirstItem"));
            liste.Add(new OlonaModel(2,
                "Second Item"));
        }
    }
}

1 个答案:

答案 0 :(得分:0)

根据您的描述,有一个选项卡式页面,两个页面,一个是列表页面,另一个是详细信息页面,您想在列表页面中选择列表视图项,然后其他详细信息将显示详细信息页面,对吗?

如果是,我建议您可以这样做:

标签页:

<TabbedPage
x:Class="App4.TabbedPage2"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:App4"
x:Name="tabbedpage2">
<!--  Pages can be added as references or inline  -->
<TabbedPage.Children>
    <local:ListPage Title="Mian page" BindingContext="{Binding}" />
    <local:DetailPage Title="Detail page" BindingContext="{Binding select}" />
</TabbedPage.Children>

  public partial class TabbedPage2 : TabbedPage
{
    public TabbedPage2 ()
    {
        InitializeComponent();
        this.BindingContext = new ListePageViewModel();
    }     
}

public class OlonaModel
{
    public int Numero { get; set; }
    public string Text { get; set; }
}

public class ListePageViewModel : ViewModelBase
{
    public ObservableCollection<OlonaModel> listeOlonaVM { get; set; }
    private OlonaModel _select;
    public OlonaModel select
    {
        get { return _select; }
        set
        {
            _select = value;
            RaisePropertyChanged("select");
        }
    }
    public ListePageViewModel()
    {
        listeOlonaVM = new ObservableCollection<OlonaModel>()
        {
            new OlonaModel(){Numero=1,Text="first item"},
            new OlonaModel(){Numero=2,Text="second item"},
            new OlonaModel(){Numero=3,Text="third item"},
            new OlonaModel(){Numero=4,Text="fouth item"}

        };
        select = listeOlonaVM[0];
    }
}

列表页:

 <StackLayout>
        <ListView ItemsSource="{Binding listeOlonaVM}" SelectedItem="{Binding select}">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <StackLayout>
                            <Label Text="{Binding Numero}" />
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackLayout>

详细信息页面:

  <StackLayout>
        <Label
            HorizontalOptions="CenterAndExpand"
            Text="{Binding Text}"
            VerticalOptions="CenterAndExpand" />
    </StackLayout>

ViewModelBase 实现 INotifyPropertyChanged 接口。

 public class ViewModelBase : INotifyPropertyChanged
{

    public event PropertyChangedEventHandler PropertyChanged;


    public void RaisePropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

enter image description here