【发布时间】:2020-07-24 17:20:07
【问题描述】:
我在 xaml 中有一个“主”页面,其中包含我的 cellview。
<ContentPage.Content>
<ListView
Margin="0,15,0,0"
SelectionMode="None"
RowHeight= "150"
ItemsSource="{Binding ObjectItems}">
<ListView.ItemTemplate>
<DataTemplate>
<viewcells:ObjectItemViewCell/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage.Content>
在我的 CellView 中,我想添加 2 个转换器作为 BindableContext 并将它们集成到我的一些字段中:
<<?xml version="1.0" encoding="UTF-8"?>
<ViewCell 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:OperaMobile.Views.Postlogin"
xmlns:converterFontFamily="clr-namespace:OperaMobile.Converters"
xmlns:converterColor="clr-namespace:OperaMobile.Converters"
mc:Ignorable="d"
x:Class="OperaMobile.ViewCells.ObjectItemViewCell">
<ViewCell.BindingContext>
<converterFontFamily:BoolToStringConverter x:Key="fontFamilyConverter"/>
<!--<converterColor:BoolToStringConverter x:Key="fontFamilyConverter"/>-->
</ViewCell.BindingContext>
<ViewCell.View>
<StackLayout>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80*"/>
<ColumnDefinition Width="50*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackLayout
Padding="0,10"
Grid.Column="0"
Grid.Row="0"
Margin="15,0"
VerticalOptions="Center"
Orientation="Horizontal">
<Image Source="pin"/>
<Label FontAttributes="Bold" Text="{Binding Label}" Grid.Column="0" Grid.Row="0"/>
</StackLayout>
<StackLayout
Grid.Column="0"
Grid.Row="1"
BindableLayout.ItemsSource="{Binding InfoBox.CountDetailsItemsRows}"
Orientation="Horizontal"
Margin="13,10,0,0">
<BindableLayout.ItemTemplate>
<DataTemplate>
<StackLayout>
<Label FontAttributes="Bold" Text="{Binding BoldLabelTitle}"/>
<Label Text="{Binding LabelValue}"/>
</StackLayout>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
<ListView
Margin="15,0"
Grid.Column="0"
Grid.Row="1"
SeparatorVisibility="None"
HasUnevenRows="True"
IsEnabled="False"
VerticalScrollBarVisibility="Never"
ItemsSource="{Binding InfoBox.DetailsObjectInfos}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Grid.Column="1" Orientation="Horizontal" Padding="0" Spacing="0">
<Label FontAttributes="Bold" Text="{Binding BoldLabelTitle}" Padding="0"/>
<Label Text="{Binding LabelValue}"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<StackLayout VerticalOptions="Start" Grid.Column="1" Grid.RowSpan="2" Spacing="15" Padding="20,10" Orientation="Horizontal" HorizontalOptions="End">
<StackLayout.Resources>
<ResourceDictionary>
<converterColor:BoolToStringConverter
x:Key="colorConverter"
TrueValue="#0275BA"
FalseValue="#949494"/>
<converterFontFamily:BoolToStringConverter
x:Key="fontFamilyConverter"
TrueValue="FA-S"
FalseValue="FA-R"/>
</ResourceDictionary>
</StackLayout.Resources>
<!--"{Binding IsFavorite, Converter={StaticResource fontFamilyConverter}}-->
<Label FontSize="Medium" FontFamily="{Binding IsFavorite, Converter={StaticResource Key=fontFamilyConverter}}" TextColor="{Binding IsFavorite, Converter={StaticResource Key=fontFamilyConverter}}" Text="{StaticResource IconStar}">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Path=BindingContext.ToggleFavoriteObjectCommand}" CommandParameter="{Binding Id}"/>
</Label.GestureRecognizers>
</Label>
<Label FontSize="Medium" Style="{DynamicResource BlueColorStyle}" Text="{StaticResource IconEye}">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Path=BindingContext.ViewObjectDetailsCommand}" CommandParameter="{Binding Id}"/>
</Label.GestureRecognizers>
</Label>
<Label FontSize="Medium" Style="{DynamicResource BlueSolidColorStyle}" Text="{StaticResource IconPin}">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Path=BindingContext.ViewObjectOnMapCommand}" CommandParameter="{Binding Id}"/>
</Label.GestureRecognizers>
</Label>
</StackLayout>
</Grid>
</StackLayout>
</ViewCell.View>
</ViewCell>
这是我将 viewcell 添加为 DataTemplate 的主页的虚拟机,所以这里是:
public class SearchObjectsViewModel : BaseViewModel, INotifyPropertyChanged
{
public SearchObjectsViewModel()
{
Task.Run(async () => { await GetObjectInstancesList(); });
ToggleFavoriteObjectCommand = new Command(async(data) => await ToggleFavoriteObjects(data));
ViewObjectDetailsCommand = new Command(async (data) => await GetObjectDetails(data));
ViewObjectOnMapCommand = new Command(async (data) => await ViewObjectOnMap(data));
}
#region Properties
private string searchedText;
public string SearchedText
{
get { return searchedText; }
set
{
SetProperty(ref searchedText, value);
ObjectsSearch(searchedText);
}
}
ObservableCollection<CustomPin> _objectItems { get; set; }
public ObservableCollection<CustomPin> ObjectItems
{
get
{
return _objectItems;
}
set
{
if (_objectItems != value)
{
_objectItems = value;
OnPropertyChanged(nameof(ObjectItems));
}
}
}
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
var changed = PropertyChanged;
if (changed == null)
return;
changed.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
public ICommand ViewObjectOnMapCommand { get; set; }
public ICommand ViewObjectDetailsCommand { get; set; }
public ICommand ToggleFavoriteObjectCommand { get; set; }
#endregion
#region Methods
private async Task GetObjectInstancesList()
{
ObjectItems = new ObservableCollection<CustomPin>();
var objectsResponse = await ApiServiceProvider.GetObjectInstances();
Device.BeginInvokeOnMainThread(() =>
{
if (objectsResponse.Succeeded)
{
foreach (var item in objectsResponse.ObjectInstances)
{
CustomPin pinData = new CustomPin();
pinData.Id = item.IdObjectInstance;
pinData.Label = item.ObjectClassName;
pinData.IsFavorite = item.IsFavorite.HasValue ? item.IsFavorite.Value : false;
if (item.Points != null)
{
pinData.Position = new Position(item.Points.FirstOrDefault().Latitude, item.Points.FirstOrDefault().Longitude);
}
else
{
//add polygon
}
foreach (var s in item.Strings)
{
if (s.ShowInBallon)
{
pinData.InfoBox.DetailsObjectInfos.Add(new Models.MapModels.DetailsObjectInfo
{
BoldLabelTitle = s.ClassParameterName + ": ",
LabelValue = s.StringValue
});
}
}
foreach (var i in item.Integers)
{
if (i.ShowInBallon)
{
pinData.InfoBox.DetailsObjectInfos.Add(new Models.MapModels.DetailsObjectInfo
{
BoldLabelTitle = i.ClassParameterName + ": ",
LabelValue = i.IntValue.ToString()
});
}
}
foreach (var date in item.Dates)
{
if (date.ShowInBallon)
{
pinData.InfoBox.DetailsObjectInfos.Add(new Models.MapModels.DetailsObjectInfo
{
BoldLabelTitle = date.ClassParameterName + ": ",
LabelValue = date.DateValue.ToString()
});
}
}
ObjectItems.Add(pinData);
pinData.InfoBox.CountDetailsItemsRows = pinData.InfoBox.DetailsObjectInfos.Count * 85;
}
}
TemporalData.ObjectsData = ObjectItems;
OnPropertyChanged(nameof(ObjectItems));
OnPropertyChanged(nameof(TemporalData.ObjectsData));
});
}
private void ObjectsSearch(string searchedText)
{
if (!string.IsNullOrWhiteSpace(searchedText))
{
var result = TemporalData.ObjectsData.Where(x => x.Label.ToLowerInvariant().Contains(searchedText.ToLowerInvariant())).ToList();
ObjectItems = new ObservableCollection<CustomPin>(result);
}
else
{
ObjectItems = new ObservableCollection<CustomPin>(TemporalData.ObjectsData);
}
OnPropertyChanged(nameof(ObjectItems));
}
private async Task ViewObjectOnMap(object objectId)
{
CustomPin selectedPin = App.SelectedPin = ObjectItems.Where(x => x.Id == Convert.ToInt32(objectId)).FirstOrDefault();
App.GoToPinCommand = new Command(() => App.GoToPinCommand.Execute(selectedPin));
await Shell.Current.GoToAsync(Routes.MapPage);
}
private async Task GetObjectDetails(object objectId)
{
App.SelectedPin = ObjectItems.Where(x => x.Id == Convert.ToInt32(objectId)).FirstOrDefault();
await Shell.Current.GoToAsync(Routes.ItemDetailsPage);
}
private async Task ToggleFavoriteObjects(object objectId)
{
int id = Convert.ToInt32(objectId);
var objectItem = ObjectItems.Where(x => x.Id == id).FirstOrDefault();
var favoriteToggleResponse = await ApiServiceProvider.ToggleFavoriteObjectById(id, !objectItem.IsFavorite);
if (!favoriteToggleResponse.Succeeded)
{
await Shell.Current.DisplayAlert("Error", "Lost communication with server. Try again.", "OK");
}
else
{
ObjectItems.Where(x => x.Id == id).Select(c => { c.IsFavorite = !c.IsFavorite; return c; }).ToList();
}
}
#endregion
}
我收到错误:BindingCOntext is set more than once.
我遇到的其他问题是模拟器无法识别 TapGestureRecognizer 例如这个标签,您可以参考代码:
<Label FontSize="Medium" FontFamily="{Binding IsFavorite, Converter={StaticResource Key=fontFamilyConverter}}" TextColor="{Binding IsFavorite, Converter={StaticResource Key=fontFamilyConverter}}" Text="{StaticResource IconStar}">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Path=BindingContext.ToggleFavoriteObjectCommand}" CommandParameter="{Binding Id}"/>
</Label.GestureRecognizers>
</Label>
我需要输入Command="{Binding Path=BindingContext.ToggleFavoriteObjectCommand,Source={x:Reference Page}}" 之类的内容,但我不知道在我的情况下是否可以引用“父页面”,这将是我调用 cellView 的“主”页面。
【问题讨论】:
标签: c# xaml xamarin xamarin.forms