Xamarin.Forms绑定不起作用

时间:2017-06-01 02:56:23

标签: c# xaml xamarin mvvm xamarin.forms

我尝试使用XAML将Windows10的UWP C#应用程序重写为Xamarin应用程序。但Binding(例如 ,例如ListView ItemSource = ... )对我不起作用,我不知道为什么。

  

Visual Studio告诉我,由于未知的数据上下文,无法解析符号记录。

以下是我的XAML( MainPage.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:local="clr-namespace:XamarinTest;assembly=XamarinTest"
             x:Class="XamarinTest.MainPage">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
            <RowDefinition Height="100" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="100" />
        </Grid.ColumnDefinitions>
        <ListView x:Name="listView" IsVisible="false" ItemsSource="{Binding Recording}">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <ViewCell.View>
                            <StackLayout Orientation="Horizontal">
                                <Image Source="Accept" WidthRequest="40" HeightRequest="40" />
                                <StackLayout Orientation="Vertical" HorizontalOptions="StartAndExpand">
                                    <Label Text="TEST" HorizontalOptions="FillAndExpand" />
                                    <Label Text="TEST" />
                                </StackLayout>
                            </StackLayout>
                        </ViewCell.View>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>
</ContentPage>

这是C#( MainPage.xaml.cs ):

namespace XamarinTest
{
    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            this.InitializeComponent();
            this.AllTestViewModel = new RecordingViewModel();
            this.BindingContext = AllTestViewModel;                
        }
        public RecordingViewModel AllTestViewModel { get; set; }
    }
}

最后是ViewModel( RecordingViewModel.cs ):

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using XamarinTest.Model;

namespace XamarinTest.ViewModel
{
    public class RecordingViewModel : INotifyPropertyChanged
    {
        public ObservableCollection<Recording> Recordings { get; } = new TrulyObservableCollection<Recording>();

        public RecordingViewModel()
        {
            Recordings.Add(new RecordingTest2()
            {
                TestName = "Test 1",
                TestNote = "Vytvoreni DB",
                TestTime = new TimeSpan(0, 0, 0)
            });
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    public sealed class TrulyObservableCollection<T> : ObservableCollection<T>
        where T : INotifyPropertyChanged
    {
        public TrulyObservableCollection()
        {
            CollectionChanged += FullObservableCollectionCollectionChanged;
        }

        public TrulyObservableCollection(IEnumerable<T> pItems) : this()
        {
            foreach (var item in pItems)
            {
                this.Add(item);
            }
        }

        private void FullObservableCollectionCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.NewItems != null)
            {
                foreach (Object item in e.NewItems)
                {
                    ((INotifyPropertyChanged)item).PropertyChanged += ItemPropertyChanged;
                }
            }
            if (e.OldItems != null)
            {
                foreach (Object item in e.OldItems)
                {
                    ((INotifyPropertyChanged)item).PropertyChanged -= ItemPropertyChanged;
                }
            }
        }

        private void ItemPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            NotifyCollectionChangedEventArgs args = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, sender, sender, IndexOf((T)sender));
            OnCollectionChanged(args);
        }
    }
}

所有内容(模型和视图模型)都在本机UWP Windows 10应用程序中运行。只有绑定和制作相同的视图才是Xamarin的问题。有人可以帮忙绑定吗? THX。

修改

Recording.cs 就在这里:

using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace XamarinTest.Model
{
    public abstract class Recording : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public string TestName { get; set; }
        private TimeSpan _testTime;
        private string _testNote;
        private string _actualIco = "Play";
        private bool _isActive = false;
        private bool _enabled = true;
        public double IcoOpacity { get; private set; } = 1.0;
        public string ActualIco
        {
            get => _actualIco;
            set
            {
                if (_actualIco == null) _actualIco = "Admin";
                _actualIco = value;
                NotifyPropertyChanged("ActualIco");
            }
        }
        public bool IsActive
        {
            get => _isActive;
            set
            {
                if (_isActive == value) return;
                _isActive = value;
                IcoOpacity = !value ? 1.0 : 0.3;
                NotifyPropertyChanged("IsActive");
                NotifyPropertyChanged("IcoOpacity");
            }
        }
        public bool Enabled
        {
            get => _enabled;
            set
            {
                if (_enabled == value) return;
                _enabled = value;
                NotifyPropertyChanged("Enabled");
            }
        }
        public string TestNote
        {
            get => _testNote;
            set
            {
                if (_testNote == value) return;
                _testNote = value;
                NotifyPropertyChanged("TestNote");
            }
        }
        public TimeSpan TestTime
        {
            get => _testTime;
            set
            {
                if (_testTime == value) return;
                _testTime = value;
                NotifyPropertyChanged("TestTime");
            }
        }

        protected Recording()
        {
            TestName = "Unkonwn";
            TestNote = "";
            _testTime = new TimeSpan(0, 0, 0);
        }

        protected Recording(string testName, string testNote, TimeSpan testTime)
        {
            TestName = testName;
            TestNote = testNote;
            _testTime = testTime;
        }
        public string OneLineSummary => $"{TestName}, finished: "
                                        + TestTime;

        private void NotifyPropertyChanged(string propertyName = "")
        {
            var handler = PropertyChanged;
            handler?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        public abstract bool playTest();

    }
}

我尝试在XAML中添加DataContext(原始问题中的postet),因为这样的智能:

xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
xmlns:dvm="clr-namespace:XamarinTest.ViewModel"
xmlns:system="clr-namespace:System;assembly=System.Runtime"
d:DataContext="{system:Type dvm:RecordingViewModel}"

这到Grid:

<Label Text="{Binding Recordings[0].TestName}" Grid.Row="0" Grid.Column="2" />

IntelliSence没问题,但文字没有在应用中显示。

2 个答案:

答案 0 :(得分:3)

终于工作了!

XAML应该看起来像下面的代码。 Imporant是xmls:viewModel="..."<ContentPage.BindingContext>...</>

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"                                                  
             xmlns:viewModel="clr-namespace:XamarinTest.ViewModel;assembly=XamarinTest"
             x:Class="XamarinTest.MainPage"         
             >
    <ContentPage.BindingContext>
        <viewModel:RecordingViewModel/>
    </ContentPage.BindingContext>
<ListView x:Name="listView" ItemsSource="{Binding Recordings}" Grid.Row="1" Grid.Column="1">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <ViewCell.View>
                            <StackLayout Orientation="Horizontal">
                                <Image Source="Accept" WidthRequest="40" HeightRequest="40" />
                                <StackLayout Orientation="Vertical" HorizontalOptions="StartAndExpand">
                                    <Label Text="{Binding TestName}" HorizontalOptions="FillAndExpand" />
                                    <Label Text="{Binding TestNote}" />
                                </StackLayout>
                            </StackLayout>
                        </ViewCell.View>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>
</ContentPage>

和MainPage.xaml.cs是okey

namespace XamarinTest
{
    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            this.InitializeComponent();
            this.AllTestViewModel = new RecordingViewModel();
            this.BindingContext = AllTestViewModel;                
        }
        public RecordingViewModel AllTestViewModel { get; set; }
    }
}

答案 1 :(得分:0)

查看您的ViewModel,看起来没有Recording成员,但您确实拥有Recordings成员。

修改

所以你要在后面的代码中添加你的DataContext,所以忽略Xaml部分。

您的视图(MainPage.xaml)具有ViewModel(RecordingViewModel.cs)。 ViewModel有一个名为Recording s 的成员(记录类型的集合)。但是在您的Xaml中,您尝试绑定到录制

变化:

<ListView x:Name="listView" IsVisible="false" ItemsSource="{Binding Recording}">

为:

<ListView x:Name="listView" IsVisible="false" ItemsSource="{Binding Recordings}">

第二次编辑

你的例子中唯一的Label是ListView里面的那个是吗?

如果是这样,您可以通过以下方式访问RecordingsTestNote子女孩。