CarouselView与不同的ContentViews绑定ViewModel

时间:2017-03-06 15:24:08

标签: c# xamarin xamarin.forms

我正在尝试将我的CarouselPage转换为CarouselView。 在我的CarouselPage中,我有一些ContentPages,我转换为ContentViews。 现在我将ContentViews添加到CarouselView。

<forms:CarouselView ItemsSource="{Binding ContentViews}">
 <forms:CarouselView.ItemTemplate>
  <DataTemplate>
   <ContentView Content="{Binding Content}" />/
  </DataTemplate>
 </forms:CarouselView.ItemTemplate>
</forms:CarouselView>

//视图模型

private List<ContentView> _contentViews;
public List<ContentView> ContentViews
    {
        get { return _contentViews; }
        set { SetProperty(ref _contentViews, value); }
    }
public TestVM(){{ContentViews = new List<ContentView> { new Selector(), new TestView() };}

它工作正常,但我失去了数据绑定。 现在我想知道如何将ViewModel绑定到Carousel视图中的Views,或者我是否可以将它们绑定到Carousel的“Parent”Viewmodel。

4 个答案:

答案 0 :(得分:1)

我做了一个类似的解决方案,但是做了一个额外的容器来组合ContentView / ViewModel:

这里有全局轮播视图:

        <CarouselView ItemsSource="{Binding ContentViews}">
            <CarouselView.ItemTemplate>
                <DataTemplate>
                    <ContentView Content="{Binding Content}" BindingContext="{Binding ViewModel}" />
                </DataTemplate>
            </CarouselView.ItemTemplate>
        </CarouselView>

ContentPage的构造函数,它是包含轮播的viewmodel:

        public ContainerViewModel()
    {
        _contentViews = new ObservableCollection<ContentViewWithVM>();
        ContentViews.Add(new ContentViewWithVM
        {
            Content = new Page1View(),
            ViewModel = this //Or any other viewmodel
        });
        ContentViews.Add(new ContentViewWithVM
        {
            Content = new Page2View(),
            ViewModel = this
        });
        ContentViews.Add(new ContentViewWithVM
        {
            Content = new Page3View(),
            ViewModel = this
        });
    }

带有ViewModel / View的简单容器

public class ContentViewWithVM : BindableObject
{
    public ContentView _content;
    public object _viewModel; //Choose a base viewmodel, object just for reference

    public object ViewModel
    {
        get
        {
            return _viewModel;
        }

        set
        {
            _viewModel = value;
            OnPropertyChanged();
        }
    }

    public ContentView Content
    {
        get
        {
            return _content;
        }

        set
        {
            _content = value;
            OnPropertyChanged();
        }
    }
}

答案 1 :(得分:0)

您做得很好,但通常情况下,您的视图模型不应该包含您的内容视图列表(根据定义,它应该在视图中管理)。

我所做的是在我的内容页面中创建我的内容视图,就像在xaml.cs中一样:

std::initializer_list

答案 2 :(得分:0)

我找到了解决方案: 我将内容设置为视图的内容,但是绑定是在视图的内容之外设置的。 现在我将Binding放在最终有效的View内容中。

<ContentView.Content>
    <StackLayout>
        <StackLayout.BindingContext>
            <viewModels:TestViewModel />
        </StackLayout.BindingContext>
        <BoxView BackgroundColor="{Binding Colorback}"></BoxView>
        <Label Text="Test" ></Label>
    </StackLayout>
</ContentView.Content>

答案 3 :(得分:0)

在我的ViewModel中,我以这种方式创建了ItemSource ViewModels,我可以将不同的ViewModel绑定到轮播中的每个视图。然后我创建一个DataTemplateSelector来处理Views和ViewModels的匹配。

ViewModel代码:

public class HomeViewModel
{
    public HomeViewModel()
    {
        Views = new ObservableCollection<ViewModelBase>
        {
            new SomeViewModel1(),
            new SomeViewModel2()
            new SomeViewModel3(),
            new SomeViewModel4()
        };
    }

    public ObservableCollection<ViewModelBase> Views { get; set; }
}

ViewModelBase:

public class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public void RaisePropertyChanged(string name)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }
}

HomeViewSelector:

public class HomeViewSelector : DataTemplateSelector
{
    public DataTemplate ViewTemplate1 { get; set; }
    public DataTemplate ViewTemplate2 { get; set; }
    public DataTemplate ViewTemplate3 { get; set; }
    public DataTemplate ViewTemplate4 { get; set; }

    protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
    {
        var tab = (ViewTab)item;
        DataTemplate template = null;

        switch (tab.SelectedTab)
        {
            case CarouselViewTabs.View1:
                template = ViewTemplate1;
                break;
            case CarouselViewTabs.View2:
                template = ViewTemplate2;
                break;
            case CarouselViewTabs.View3:
                template = ViewTemplate3;
                break;
            case CarouselViewTabs.View4:
                template = ViewTemplate4;
                break;
            default:
                throw new NotSupportedException();
        }

        return template;
    }
}

Home.xaml:

<?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:cv="clr-namespace:CarouselView.FormsPlugin.Abstractions;assembly=CarouselView.FormsPlugin.Abstractions"
             xmlns:v="clr-namespace:Views"
             xmlns:s="clr-namespace:Selectors"
             x:Class="WeddingPhotos.Mobile.Views.HomePage">
    <ContentPage.Resources>
        <ResourceDictionary>
            <DataTemplate x:Key="ViewTemplate1">
                <v:SomeView1 BindingContext="{Binding BindingContext.ViewModel}" />
            </DataTemplate>
            <DataTemplate x:Key="SomeView2">
                <v:SomeView2 BindingContext="{Binding BindingContext.ViewModel}" />
            </DataTemplate>
            <DataTemplate x:Key="SomeView3">            
                <v:SomeView3 BindingContext="{Binding BindingContext.ViewModel}" />
            </DataTemplate>
            <DataTemplate x:Key="SomeView4">
                <v:SomeView4 BindingContext="{Binding BindingContext.ViewModel}" />
            </DataTemplate>
            <s:HomeViewSelector x:Key="HomeViewSelector"
                                SomeView1="{StaticResource ViewTemplate1}"
                                SomeView2="{StaticResource ViewTemplate2}"
                                SomeView3="{StaticResource ViewTemplate3}"
                                SomeView4="{StaticResource ViewTemplate4}"/>
        </ResourceDictionary>
    </ContentPage.Resources>
    <ContentPage.Content>
        <StackLayout>           
            <cv:CarouselViewControl ItemsSource="{Binding Tabs}"
                                    ItemTemplate="{StaticResource HomeViewSelector}" />
        </StackLayout>
    </ContentPage.Content>
</ContentPage>