【问题标题】:CarouselView with different ContentViews Binding ViewModelCarouselView 与不同的 ContentViews 绑定 ViewModel
【发布时间】:2017-03-06 15:24:07
【问题描述】:

我正在尝试将我的 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 视图中的视图,或者我是否可以将它们绑定到 Carousel 的“父”视图模型。

【问题讨论】:

    标签: c# xamarin xamarin.forms


    【解决方案1】:

    在我的ViewModel 中,我创建了一个 ViewModel 的ItemSource,这样我可以将不同的 ViewModel 绑定到轮播中的每个视图。然后我创建一个处理视图和视图模型匹配的 DataTemplateSelector。

    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>
    

    【讨论】:

    • aaaaaaaa 我快疯了,请帮忙。在整个网络和此页面上,人们都使用这种示例:` ` 但每当我这样做时,我都会收到错误消息无法分配属性“ItemTemplate”.. .. !!! ……这是怎么回事??!!
    • 发生了什么事?你受黑猩猩的摆布。您的“CarouselView”对象需要来自 CarouselView.Forms.Plugin 而不是 Xamarin.Forms。前者具有您需要的属性,而后者只是一个“黑猩猩占位符元素”
    【解决方案2】:

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

    这是全局轮播视图:

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

    ContentPage 的构造函数是包含轮播的视图模型:

            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();
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

      我找到了解决方案: 我将内容设置为视图的内容,但绑定是在视图的内容之外设置的。 现在我将 Binding 放在 View 的 Content 中,它终于可以工作了。

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

      【讨论】:

        【解决方案4】:

        你做得很好,除了通常情况下,你的视图模型不应该保存你的内容视图列表(根据定义,它应该在视图中管理)。

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

        CarouselView.ItemSource = new List<View>
        {
            new ContentPage{ BindingContext = myCurrentViewModel},
            new ContentPage{ BindingContext = myCurrentViewModel},
        ...
        }
        

        【讨论】:

        • 您的 Xaml 是什么样的?因为当我尝试你的方法时,我仍然没有任何绑定。
        • 我的xaml和你的一样
        猜你喜欢
        • 2020-03-12
        • 1970-01-01
        • 1970-01-01
        • 2017-11-17
        • 2012-06-11
        • 1970-01-01
        • 2015-11-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多