This commit is contained in:
ShaneN 2019-10-14 23:19:46 -06:00
Родитель 9d2e950803 773232214c
Коммит fba3e9337b
73 изменённых файлов: 2317 добавлений и 638 удалений

Просмотреть файл

@ -51,11 +51,7 @@ namespace Xamarin.Forms.Platform
[RenderWith (typeof (ButtonRenderer))]
internal class _ButtonRenderer { }
#if __ANDROID__
[RenderWith(typeof(ImageButtonRenderer))]
#elif !TIZEN4_0
[RenderWith(typeof(ImageButtonRenderer))]
#endif
internal class _ImageButtonRenderer { }
[RenderWith (typeof (TableViewRenderer))]
@ -63,12 +59,18 @@ namespace Xamarin.Forms.Platform
[RenderWith (typeof (ListViewRenderer))]
internal class _ListViewRenderer { }
#if !TIZEN4_0
#if !TIZEN4_0
[RenderWith (typeof (CollectionViewRenderer))]
internal class _CollectionViewRenderer { }
[RenderWith (typeof (CarouselViewRenderer))]
internal class _CarouselViewRenderer { }
#else
[RenderWith (typeof (ItemsViewRenderer))]
#endif
internal class _CollectionViewRenderer { }
#if !TIZEN4_0
[RenderWith (typeof (CarouselViewRenderer))]
#endif
internal class _CarouselViewRenderer { }
[RenderWith (typeof (SliderRenderer))]
internal class _SliderRenderer { }

Просмотреть файл

@ -495,7 +495,22 @@ namespace Xamarin.Forms.Build.Tasks
if (indexArg != null) {
var defaultMemberAttribute = previousPartTypeRef.GetCustomAttribute(module, ("mscorlib", "System.Reflection", "DefaultMemberAttribute"));
var indexerName = defaultMemberAttribute?.ConstructorArguments?.FirstOrDefault().Value as string ?? "Item";
var indexer = previousPartTypeRef.GetProperty(pd => pd.Name == indexerName && pd.GetMethod != null && pd.GetMethod.IsPublic, out var indexerDeclTypeRef);
PropertyDefinition indexer = null;
TypeReference indexerDeclTypeRef = null;
if (int.TryParse(indexArg, out _))
indexer = previousPartTypeRef.GetProperty(pd => pd.Name == indexerName
&& pd.GetMethod != null
&& TypeRefComparer.Default.Equals(pd.GetMethod.Parameters[0].ParameterType, module.ImportReference(("mscorlib", "System", "Int32")))
&& pd.GetMethod.IsPublic, out indexerDeclTypeRef);
indexer = indexer ?? previousPartTypeRef.GetProperty(pd => pd.Name == indexerName
&& pd.GetMethod != null
&& TypeRefComparer.Default.Equals(pd.GetMethod.Parameters[0].ParameterType, module.ImportReference(("mscorlib", "System", "String")))
&& pd.GetMethod.IsPublic, out indexerDeclTypeRef);
indexer = indexer ?? previousPartTypeRef.GetProperty(pd => pd.Name == indexerName
&& pd.GetMethod != null
&& TypeRefComparer.Default.Equals(pd.GetMethod.Parameters[0].ParameterType, module.ImportReference(("mscorlib", "System", "String")))
&& pd.GetMethod.IsPublic, out indexerDeclTypeRef);
properties.Add((indexer, indexerDeclTypeRef, indexArg));
var indexType = indexer.GetMethod.Parameters[0].ParameterType.ResolveGenericParameters(indexerDeclTypeRef);
if (!TypeRefComparer.Default.Equals(indexType, module.TypeSystem.String) && !TypeRefComparer.Default.Equals(indexType, module.TypeSystem.Int32))

Просмотреть файл

@ -11,11 +11,9 @@ namespace Xamarin.Forms.Build.Tasks
{
static string GetAssembly(TypeReference typeRef)
{
var md = typeRef.Scope as ModuleDefinition;
if (md != null)
if (typeRef.Scope is ModuleDefinition md)
return md.Assembly.FullName;
var anr = typeRef.Scope as AssemblyNameReference;
if (anr != null)
if (typeRef.Scope is AssemblyNameReference anr)
return anr.FullName;
throw new ArgumentOutOfRangeException(nameof(typeRef));
}

Просмотреть файл

@ -42,10 +42,11 @@
<WarningLevel>4</WarningLevel>
<AndroidLinkMode>None</AndroidLinkMode>
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
<AndroidUseSharedRuntime>false</AndroidUseSharedRuntime>
<AndroidSupportedAbis>armeabi-v7a;x86</AndroidSupportedAbis>
<Debugger>Xamarin</Debugger>
<DevInstrumentationEnabled>True</DevInstrumentationEnabled>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<AndroidSupportedAbis>armeabi-v7a</AndroidSupportedAbis>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<Optimize>true</Optimize>
@ -55,9 +56,15 @@
<WarningLevel>4</WarningLevel>
<AndroidLinkMode>SdkOnly</AndroidLinkMode>
<EmbedAssembliesIntoApk>True</EmbedAssembliesIntoApk>
<AndroidSupportedAbis>armeabi-v7a,x86</AndroidSupportedAbis>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition="'$(TF_BUILD)' == 'true' OR '$(CI)' == 'true'">
<AndroidLinkMode>Full</AndroidLinkMode>
<AndroidUseSharedRuntime>False</AndroidUseSharedRuntime>
<EmbedAssembliesIntoApk>True</EmbedAssembliesIntoApk>
<AndroidSupportedAbis>armeabi-v7a,x86</AndroidSupportedAbis>
<AndroidEnableMultiDex>true</AndroidEnableMultiDex>
</PropertyGroup>
<PropertyGroup Condition=" '$(CI)' == 'True' ">
<AndroidLinkMode>Full</AndroidLinkMode>
<AndroidUseSharedRuntime>False</AndroidUseSharedRuntime>
@ -385,4 +392,4 @@
</CreateItem>
<Copy SourceFiles="@(MapsKey)" DestinationFiles="Properties\MapsKey.cs" Condition="!Exists('Properties\MapsKey.cs')" />
</Target>
</Project>
</Project>

Просмотреть файл

@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.Text;
using Xamarin.Forms.CustomAttributes;
using Xamarin.Forms.Internals;
#if UITEST
using Xamarin.Forms.Core.UITests;
using Xamarin.UITest;
using NUnit.Framework;
#endif
namespace Xamarin.Forms.Controls.Issues
{
#if UITEST
[Category(UITestCategories.CollectionView)]
#endif
[Preserve(AllMembers = true)]
[Issue(IssueTracker.Github, 6963, "[Bug] CollectionView multiple pre-selection throws ArgumentOutOfRangeException when SelectedItems is bound to an ObservableCollection initialized inside the constructor.",
PlatformAffected.iOS | PlatformAffected.UWP)]
public class Issue6963 : TestNavigationPage
{
protected override void Init()
{
#if APP
FlagTestHelpers.SetCollectionViewTestFlag();
PushAsync(new GalleryPages.CollectionViewGalleries.SelectionGalleries.SelectionSynchronization());
#endif
}
#if UITEST
[Test]
public void SelectedItemsNotInSourceDoesNotCrash()
{
// If this page didn't crash, then we're good
RunningApp.WaitForElement("FirstLabel");
}
#endif
}
}

Просмотреть файл

@ -0,0 +1,112 @@
using System;
using System.Collections.Generic;
using Xamarin.Forms.CustomAttributes;
using Xamarin.Forms.Internals;
#if UITEST
using NUnit.Framework;
using Xamarin.Forms.Core.UITests;
using System.Linq;
#endif
namespace Xamarin.Forms.Controls.Issues
{
#if UITEST
[Category(UITestCategories.CollectionView)]
#endif
[Preserve(AllMembers = true)]
[Issue(IssueTracker.Github, 7742, "(iOS) Changing ItemTemplate does not work as expected", PlatformAffected.iOS)]
public class Issue7742 : TestContentPage
{
CollectionView _collectionView;
public Issue7742()
{
Title = "Issue 7742";
}
protected override void Init()
{
var instructions = new Label
{
Text = "Click the Button. If all cells render correctly, then the test passes."
};
var button = new Button
{
Text = "Change ItemTemplate",
AutomationId = "TemplateBtn"
};
button.Clicked += OnButton1Clicked;
_collectionView = new CollectionView
{
BackgroundColor = Color.LightGreen,
SelectionMode = SelectionMode.None,
HeightRequest = 500
};
var lines = new List<Issue7742Model>();
for (int i = 0; i < 30; i++)
{
lines.Add(new Issue7742Model() { Text = $"Item {i}" });
}
_collectionView.ItemsSource = lines;
var stack = new StackLayout();
stack.Children.Add(instructions);
stack.Children.Add(button);
stack.Children.Add(_collectionView);
Content = stack;
}
void OnButton1Clicked(object sender, EventArgs e)
{
_collectionView.ItemTemplate = CreateDataGridTemplate(2);
}
DataTemplate CreateDataGridTemplate(int columns)
{
var template = new DataTemplate(() =>
{
var grid = new Grid() { Padding = new Thickness(0), Margin = 0, RowSpacing = 0, ColumnSpacing = 0 };
grid.RowDefinitions.Clear();
grid.ColumnDefinitions.Clear();
grid.Children.Clear();
grid.RowDefinitions.Add(new RowDefinition() { Height = 40 });
grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) });
Label cell;
cell = new Label() { };
cell.SetBinding(Label.TextProperty, "Text");
cell.FontSize = 20;
cell.FontAttributes = FontAttributes.Bold;
cell.BackgroundColor = Color.LightBlue;
grid.Children.Add(cell, 0, 0);
for (int i = 0; i < columns; i++)
{
grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) });
cell = new Label() { };
cell.Text = "Col:" + i;
cell.FontAttributes = FontAttributes.Bold;
cell.BackgroundColor = Color.Beige;
grid.Children.Add(cell, i + 1, 0);
}
return grid;
});
return template;
}
}
[Preserve(AllMembers = true)]
public class Issue7742Model
{
public string Text { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8" ?>
<controls:TestContentPage
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:controls="clr-namespace:Xamarin.Forms.Controls"
mc:Ignorable="d"
x:Class="Xamarin.Forms.Controls.Issues.Issue7758">
<ContentPage.Resources>
<ResourceDictionary>
<Style TargetType="StackLayout" x:Key="StackLayoutStyle">
<Setter Property="Orientation" Value="Vertical"/>
<Setter Property="HorizontalOptions" Value="Center"/>
<Setter Property="VerticalOptions" Value="Center"/>
<Setter Property="Padding" Value="20, 0"/>
<Setter Property="Spacing" Value="10"/>
<Setter Property="BackgroundColor" Value="Wheat"/>
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<Grid RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0" BackgroundColor="Black" Padding="10">
<Label Text="If the red line is not between Item 3 and Item 4, the test has failed. Change device orientation to landscape. If the red line is not between Item 3 and Item 4, the test has failed. If there is a visible white background during orientation change, the test has failed." TextColor="White"/>
</Grid>
<CollectionView Grid.Row="1">
<CollectionView.EmptyView>
<ContentView HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" BackgroundColor="Beige">
<StackLayout Style="{x:StaticResource StackLayoutStyle}">
<Label Text="Text1" HorizontalTextAlignment="Center" FontAttributes="Bold" FontSize="14.5"/>
<Label Text="Text2" HorizontalTextAlignment="Center" TextColor="#636571" FontSize="14.5"/>
<Label Text="Text3" HorizontalTextAlignment="Center" FontAttributes="Bold" FontSize="14.5"/>
<Label Text="Text4" HorizontalTextAlignment="Center" TextColor="#636571" FontSize="14.5"/>
<Label Text="Text5" HorizontalTextAlignment="Center" FontAttributes="Bold" FontSize="14.5"/>
<Label Text="Text6" HorizontalTextAlignment="Center" TextColor="#636571" FontSize="14.5"/>
</StackLayout>
</ContentView>
</CollectionView.EmptyView>
</CollectionView>
<Grid Grid.Row="2" BackgroundColor="Black" HeightRequest="50"/>
<Grid Grid.Row="1" BackgroundColor="Red" HeightRequest="5" VerticalOptions="Center"/>
</Grid>
</controls:TestContentPage>

Просмотреть файл

@ -0,0 +1,25 @@
using System.Collections.Generic;
using Xamarin.Forms.CustomAttributes;
using Xamarin.Forms.Internals;
namespace Xamarin.Forms.Controls.Issues
{
[Preserve(AllMembers = true)]
[Issue(IssueTracker.Github, 7758, "[iOS] EmptyView is not rendered in screen center", PlatformAffected.iOS)]
public partial class Issue7758 : TestContentPage
{
public Issue7758()
{
#if APP
Device.SetFlags(new List<string> { CollectionView.CollectionViewExperimental });
InitializeComponent();
#endif
}
protected override void Init()
{
}
}
}

Просмотреть файл

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8" ?>
<controls:TestContentPage 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:controls="clr-namespace:Xamarin.Forms.Controls"
mc:Ignorable="d"
x:Class="Xamarin.Forms.Controls.Issues.Issue7789">
<ContentPage.Content>
<StackLayout Margin="10">
<Label
Text="If the CarouselView below is rendered without problems, the test passes."/>
<CarouselView
BackgroundColor="GreenYellow">
<CarouselView.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>Baboon</x:String>
<x:String>Capuchin Monkey</x:String>
<x:String>Blue Monkey</x:String>
<x:String>Squirrel Monkey</x:String>
<x:String>Golden Lion Tamarin</x:String>
<x:String>Howler Monkey</x:String>
<x:String>Japanese Macaque</x:String>
<x:String>Mandrill</x:String>
<x:String>Proboscis Monkey</x:String>
<x:String>Red-shanked Douc</x:String>
<x:String>Gray-shanked Douc</x:String>
<x:String>Golden Snub-nosed Monkey</x:String>
<x:String>Black Snub-nosed Monkey</x:String>
<x:String>Tonkin Snub-nosed Monkey</x:String>
<x:String>Thomas's Langur</x:String>
<x:String>Purple-faced Langur</x:String>
<x:String>Gelada</x:String>
</x:Array>
</CarouselView.ItemsSource>
</CarouselView>
</StackLayout>
</ContentPage.Content>
</controls:TestContentPage>

Просмотреть файл

@ -0,0 +1,38 @@
using Xamarin.Forms.CustomAttributes;
using Xamarin.Forms.Internals;
using Xamarin.Forms.Xaml;
using System.Collections.Generic;
#if UITEST
using Xamarin.UITest;
using Xamarin.UITest.Queries;
using NUnit.Framework;
using Xamarin.Forms.Core.UITests;
#endif
namespace Xamarin.Forms.Controls.Issues
{
#if UITEST
[NUnit.Framework.Category(UITestCategories.CollectionView)]
#endif
#if APP
[XamlCompilation(XamlCompilationOptions.Compile)]
#endif
[Preserve(AllMembers = true)]
[Issue(IssueTracker.Github, 7789, "CarouselView crash when displaying strings", PlatformAffected.iOS)]
public partial class Issue7789 : TestContentPage
{
public Issue7789()
{
#if APP
Device.SetFlags(new List<string> { CollectionView.CollectionViewExperimental });
InitializeComponent();
#endif
}
protected override void Init()
{
}
}
}

Просмотреть файл

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8" ?>
<controls:TestContentPage 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:controls="clr-namespace:Xamarin.Forms.Controls"
mc:Ignorable="d"
x:Class="Xamarin.Forms.Controls.Issues.Issue7792"
Title="Issue 7792" >
<ContentPage.Content>
<StackLayout>
<Label
Text="If you can see the text of the Carousel EmptyView below, the test passes."/>
<CarouselView
BackgroundColor="Yellow"
ItemsSource="{Binding IteEmptyItemsms}"
EmptyView="No items to display (EmptyView)." />
</StackLayout>
</ContentPage.Content>
</controls:TestContentPage>

Просмотреть файл

@ -0,0 +1,45 @@
using System.Collections.Generic;
using Xamarin.Forms.CustomAttributes;
using Xamarin.Forms.Internals;
using System.Windows.Input;
#if UITEST
using Xamarin.UITest;
using NUnit.Framework;
using Xamarin.UITest.iOS;
#endif
namespace Xamarin.Forms.Controls.Issues
{
[Preserve(AllMembers = true)]
[Issue(IssueTracker.Github, 7792, "(Android) CarouselView string EmptyView not displayed", PlatformAffected.Android)]
public partial class Issue7792 : TestContentPage
{
public Issue7792()
{
#if APP
Device.SetFlags(new List<string> { CollectionView.CollectionViewExperimental });
InitializeComponent();
#endif
BindingContext = new Issue7792ViewModel();
}
protected override void Init()
{
}
}
[Preserve(AllMembers = true)]
public class Issue7792Model
{
public string Text1 { get; set; }
public string Text2 { get; set; }
}
[Preserve(AllMembers = true)]
public class Issue7792ViewModel : BindableObject
{
public IList<Issue7792Model> EmptyItems { get; private set; }
}
}

Просмотреть файл

@ -0,0 +1,77 @@
<?xml version="1.0" encoding="utf-8" ?>
<controls:TestContentPage 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:controls="clr-namespace:Xamarin.Forms.Controls"
xmlns:local="clr-namespace:Xamarin.Forms.Controls.Issues"
mc:Ignorable="d"
x:Class="Xamarin.Forms.Controls.Issues.Issue7817">
<ContentPage.Content>
<Grid
Margin="12">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid
Grid.Row="0"
BackgroundColor="Yellow">
<Label
LineBreakMode="WordWrap"
Text="Change ItemsUpdatingScrollMode by selecting KeepLastItemInView in the Picker and verify that the behavior changes. The CarouselView must move the scroll to the latest item added."/>
</Grid>
<StackLayout
Grid.Row="1"
Orientation="Horizontal"
HorizontalOptions="Center">
<Label
Text="UpdatingScrollMode: "
VerticalTextAlignment="Center" />
<local:EnumPicker x:Name="enumPicker"
EnumType="{x:Type ItemsUpdatingScrollMode}"
SelectedIndex="0"
SelectedIndexChanged="OnItemsUpdatingScrollModeChanged" />
</StackLayout>
<CarouselView
Grid.Row="2"
x:Name="carouselView"
ItemsSource="{Binding Monkeys}">
<CarouselView.ItemTemplate>
<DataTemplate>
<StackLayout>
<Frame HasShadow="True"
BorderColor="DarkGray"
CornerRadius="5"
Margin="20"
HeightRequest="300"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand">
<StackLayout>
<Label Text="{Binding Name}"
FontAttributes="Bold"
FontSize="Large"
HorizontalOptions="Center"
VerticalOptions="Center" />
<Image Source="{Binding ImageUrl}"
Aspect="AspectFill"
HeightRequest="150"
WidthRequest="150"
HorizontalOptions="Center" />
<Label Text="{Binding Location}"
HorizontalOptions="Center" />
<Label Text="{Binding Details}"
FontAttributes="Italic"
HorizontalOptions="Center"
MaxLines="5"
LineBreakMode="TailTruncation" />
</StackLayout>
</Frame>
</StackLayout>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
</Grid>
</ContentPage.Content>
</controls:TestContentPage>

Просмотреть файл

@ -0,0 +1,162 @@
using System;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Threading.Tasks;
using Xamarin.Forms.CustomAttributes;
using Xamarin.Forms.Internals;
using Xamarin.Forms.Xaml;
using System.Reflection;
#if UITEST
using Xamarin.UITest;
using Xamarin.UITest.Queries;
using NUnit.Framework;
using Xamarin.Forms.Core.UITests;
#endif
namespace Xamarin.Forms.Controls.Issues
{
#if UITEST
[Category(UITestCategories.CarouselView)]
#endif
#if APP
[XamlCompilation(XamlCompilationOptions.Compile)]
#endif
[Preserve(AllMembers = true)]
[Issue(IssueTracker.Github, 7817, "[Android/iOS] Changing ItemsUpdatingScrollMode has no effect on CarouselView")]
public partial class Issue7817 : TestContentPage
{
public Issue7817()
{
#if APP
Device.SetFlags(new List<string> { CollectionView.CollectionViewExperimental });
Title = "Issue 7817";
InitializeComponent();
#endif
}
protected override async void Init()
{
BindingContext = new Issue7817ViewModel();
await ((Issue7817ViewModel)BindingContext).CreateCollectionAsync();
}
void OnItemsUpdatingScrollModeChanged(object sender, EventArgs e)
{
#if APP
carouselView.ItemsUpdatingScrollMode = (ItemsUpdatingScrollMode)(sender as EnumPicker).SelectedItem;
#endif
}
}
[Preserve(AllMembers = true)]
public class EnumPicker : Picker
{
public static readonly BindableProperty EnumTypeProperty = BindableProperty.Create(nameof(EnumType), typeof(Type), typeof(EnumPicker),
propertyChanged: (bindable, oldValue, newValue) =>
{
var picker = (EnumPicker)bindable;
if (oldValue != null)
{
picker.ItemsSource = null;
}
if (newValue != null)
{
if (!((Type)newValue).GetTypeInfo().IsEnum)
throw new ArgumentException("EnumPicker: EnumType property must be enumeration type");
picker.ItemsSource = Enum.GetValues((Type)newValue);
}
});
public Type EnumType
{
set => SetValue(EnumTypeProperty, value);
get => (Type)GetValue(EnumTypeProperty);
}
}
[Preserve(AllMembers = true)]
public class Issue7817Model
{
public int Index { get; set; }
public string Name { get; set; }
public string Location { get; set; }
public string Details { get; set; }
public string ImageUrl { get; set; }
}
[Preserve(AllMembers = true)]
public class Issue7817ViewModel : BindableObject
{
const int AddItemDelay = 2000;
public ObservableCollection<Issue7817Model> Monkeys { get; private set; } = new ObservableCollection<Issue7817Model>();
public async Task CreateCollectionAsync()
{
Monkeys.Add(new Issue7817Model
{
Index = 0,
Name = "Baboon",
Location = "Africa & Asia",
Details = "Baboons are African and Arabian Old World monkeys belonging to the genus Papio, part of the subfamily Cercopithecinae.",
ImageUrl = "http://upload.wikimedia.org/wikipedia/commons/thumb/f/fc/Papio_anubis_%28Serengeti%2C_2009%29.jpg/200px-Papio_anubis_%28Serengeti%2C_2009%29.jpg"
});
await Task.Delay(AddItemDelay);
Monkeys.Add(new Issue7817Model
{
Index = 1,
Name = "Capuchin Monkey",
Location = "Central & South America",
Details = "The capuchin monkeys are New World monkeys of the subfamily Cebinae. Prior to 2011, the subfamily contained only a single genus, Cebus.",
ImageUrl = "http://upload.wikimedia.org/wikipedia/commons/thumb/4/40/Capuchin_Costa_Rica.jpg/200px-Capuchin_Costa_Rica.jpg"
});
await Task.Delay(AddItemDelay);
Monkeys.Add(new Issue7817Model
{
Index = 2,
Name = "Blue Monkey",
Location = "Central and East Africa",
Details = "The blue monkey or diademed monkey is a species of Old World monkey native to Central and East Africa, ranging from the upper Congo River basin east to the East African Rift and south to northern Angola and Zambia",
ImageUrl = "http://upload.wikimedia.org/wikipedia/commons/thumb/8/83/BlueMonkey.jpg/220px-BlueMonkey.jpg"
});
Monkeys.Add(new Issue7817Model
{
Index = 3,
Name = "Thomas's Langur",
Location = "Indonesia",
Details = "Thomas's langur is a species of primate in the family Cercopithecidae. It is endemic to North Sumatra, Indonesia. Its natural habitat is subtropical or tropical dry forests. It is threatened by habitat loss. Its native names are reungkah in Acehnese and kedih in Alas.",
ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/3/31/Thomas%27s_langur_Presbytis_thomasi.jpg/142px-Thomas%27s_langur_Presbytis_thomasi.jpg"
});
await Task.Delay(AddItemDelay);
Monkeys.Add(new Issue7817Model
{
Index = 4,
Name = "Purple-faced Langur",
Location = "Sri Lanka",
Details = "The purple-faced langur, also known as the purple-faced leaf monkey, is a species of Old World monkey that is endemic to Sri Lanka. The animal is a long-tailed arboreal species, identified by a mostly brown appearance, dark face (with paler lower face) and a very shy nature. The species was once highly prevalent, found in suburban Colombo and the \"wet zone\" villages (areas with high temperatures and high humidity throughout the year, whilst rain deluges occur during the monsoon seasons), but rapid urbanization has led to a significant decrease in the population level of the monkeys.",
ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/0/02/Semnopithèque_blanchâtre_mâle.JPG/192px-Semnopithèque_blanchâtre_mâle.JPG"
});
await Task.Delay(AddItemDelay);
Monkeys.Add(new Issue7817Model
{
Index = 5,
Name = "Gelada",
Location = "Ethiopia",
Details = "The gelada, sometimes called the bleeding-heart monkey or the gelada baboon, is a species of Old World monkey found only in the Ethiopian Highlands, with large populations in the Semien Mountains. Theropithecus is derived from the Greek root words for \"beast-ape.\" Like its close relatives the baboons, it is largely terrestrial, spending much of its time foraging in grasslands.",
ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/1/13/Gelada-Pavian.jpg/320px-Gelada-Pavian.jpg"
});
}
}
}

Просмотреть файл

@ -0,0 +1,48 @@
using Xamarin.Forms.CustomAttributes;
using Xamarin.Forms.Internals;
namespace Xamarin.Forms.Controls.Issues
{
[Preserve(AllMembers = true)]
[Issue(IssueTracker.Github, 7898, "navigation page doesn't hide previous page", PlatformAffected.macOS)]
public class Issue7898 : TestNavigationPage
{
protected override void Init()
{
Navigation.PushAsync(new ContentPage
{
BackgroundColor = Color.Yellow,
Content = new StackLayout()
{
Children = {
new Button
{
HorizontalOptions = LayoutOptions.Start,
Text = "push page",
Command = new Command(async () => await Navigation.PushAsync(new PageWithTransparency(),false))
},
new Label
{
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center,
Text = "This text should be invisible after second page pushed",
}
}
},
});
}
class PageWithTransparency : ContentPage
{
public PageWithTransparency()
{
this.BackgroundColor = Color.Red.MultiplyAlpha(0.2);
Content = new Label
{
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.CenterAndExpand,
Text = "Text on second page",
};
}
}
}
}

Просмотреть файл

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8" ?>
<controls:TestContentPage 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:controls="clr-namespace:Xamarin.Forms.Controls"
mc:Ignorable="d"
x:Class="Xamarin.Forms.Controls.Issues.Issue7943">
<ContentPage.Content>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid
Grid.Row="0"
BackgroundColor="Black">
<Label
TextColor="White"
Text="Press the buttons below to dynamically change the ItemTemplate and ItemsSource of the CollectionView. If change without problems, the test has passed."/>
</Grid>
<StackLayout
Grid.Row="1">
<Button
Text="Change Template"
Clicked="OnChangeTemplate"/>
<Button
Text="Change ItemsSource"
Clicked="OnChangeItemsSource"/>
<Button
Text="Clear ItemsSource"
Clicked="OnClearItemsSource"/>
</StackLayout>
<CollectionView
Grid.Row="2"
x:Name="collectionView">
<CollectionView.EmptyView>
<Grid
BackgroundColor="GreenYellow">
<Label
Text="No data available"
HorizontalOptions="Center"
VerticalOptions="Center"/>
</Grid>
</CollectionView.EmptyView>
</CollectionView>
</Grid>
</ContentPage.Content>
</controls:TestContentPage>

Просмотреть файл

@ -0,0 +1,94 @@
using Xamarin.Forms.Xaml;
using System;
using System.Collections.Generic;
using Xamarin.Forms.Internals;
using Xamarin.Forms.CustomAttributes;
#if UITEST
using Xamarin.UITest;
using Xamarin.UITest.Queries;
using NUnit.Framework;
using Xamarin.Forms.Core.UITests;
#endif
namespace Xamarin.Forms.Controls.Issues
{
#if UITEST
[Category(UITestCategories.CollectionView)]
#endif
#if APP
[XamlCompilation(XamlCompilationOptions.Compile)]
#endif
[Preserve(AllMembers = true)]
[Issue(IssueTracker.Github, 7943, "[Android] Crashes if EmptyView defined and ItemsSource is changed after ItemTemplate is changed", PlatformAffected.Android)]
public partial class Issue7943 : TestContentPage
{
public Issue7943()
{
#if APP
Device.SetFlags(new List<string> { CollectionView.CollectionViewExperimental });
Title = "Issue 7943";
InitializeComponent();
collectionView.ItemTemplate = new DataTemplate(() =>
{
var grid = new Grid();
var lbl1 = new Label();
lbl1.SetBinding(Label.TextProperty, "Name");
grid.Children.Add(lbl1);
var lbl2 = new Label();
lbl2.SetBinding(Label.TextProperty, "Age");
lbl2.SetValue(Grid.ColumnProperty, 1);
grid.Children.Add(lbl2);
return grid;
});
collectionView.ItemsSource = new List<Issue7943Model> { new Issue7943Model("John", 41), new Issue7943Model("Jane", 24) };
#endif
}
protected override void Init()
{
}
#if APP
void OnChangeTemplate(object sender, EventArgs e)
{
var random = new Random();
collectionView.ItemTemplate = new DataTemplate(() =>
{
var grid = new Grid();
grid.BackgroundColor = Color.FromRgb(random.Next(0, 255), random.Next(0, 255), random.Next(0, 255));
var lbl1 = new Label();
lbl1.SetBinding(Label.TextProperty, "Name");
grid.Children.Add(lbl1);
return grid;
});
}
void OnChangeItemsSource(object sender, EventArgs e)
{
collectionView.ItemsSource = new List<Issue7943Model> { new Issue7943Model("Paul", 35), new Issue7943Model("Lucy", 57) };
}
void OnClearItemsSource(object sender, EventArgs e)
{
collectionView.ItemsSource = null;
}
#endif
}
[Preserve(AllMembers = true)]
class Issue7943Model
{
public string Name { get; set; }
public int Age { get; set; }
public Issue7943Model(string name, int age)
{
Name = name;
Age = age;
}
}
}

Просмотреть файл

@ -22,6 +22,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Issue5354.xaml.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="$(MSBuildThisFileDirectory)Issue6963.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue7253.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue7621.xaml.cs">
<SubType>Code</SubType>
@ -55,9 +56,24 @@
<Compile Include="$(MSBuildThisFileDirectory)Issue7519Xaml.xaml.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="$(MSBuildThisFileDirectory)Issue7758.xaml.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="$(MSBuildThisFileDirectory)Issue7593.xaml.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="$(MSBuildThisFileDirectory)Issue7792.xaml.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="$(MSBuildThisFileDirectory)Issue7789.xaml.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="$(MSBuildThisFileDirectory)Issue7817.xaml.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="$(MSBuildThisFileDirectory)Issue7943.xaml.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="$(MSBuildThisFileDirectory)RefreshViewTests.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue7338.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ScrollToGroup.cs" />
@ -1082,11 +1098,13 @@
<Compile Include="$(MSBuildThisFileDirectory)Issue7395.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue7582.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue7563.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue7742.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue7678.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue6491.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue6127.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue7283.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue5395.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue7898.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Bugzilla22229.xaml">
@ -1404,7 +1422,19 @@
<Compile Update="$(MSBuildThisFileDirectory)Issue7357.xaml.cs">
<DependentUpon>Issue7357.xaml</DependentUpon>
</Compile>
<Compile Update="C:\Users\hartez\Documents\Xamarin\Xamarin.Forms\Xamarin.Forms.Controls.Issues\Xamarin.Forms.Controls.Issues.Shared\Issue7519Xaml.xaml.cs">
<Compile Update="$(MSBuildThisFileDirectory)Issue7792.xaml.cs">
<DependentUpon>Issue7792.xaml</DependentUpon>
</Compile>
<Compile Update="$(MSBuildThisFileDirectory)Issue7789.xaml.cs">
<DependentUpon>Issue7789.xaml</DependentUpon>
</Compile>
<Compile Update="$(MSBuildThisFileDirectory)Issue7519Xaml.xaml.cs">
<DependentUpon>Issue7519Xaml.xaml</DependentUpon>
</Compile>
<Compile Update="$(MSBuildThisFileDirectory)Issue7817.xaml.cs">
<DependentUpon>Issue7817.xaml</DependentUpon>
</Compile>
<Compile Update="$(MSBuildThisFileDirectory)Issue7519Xaml.xaml.cs">
<DependentUpon>Issue7519Xaml.xaml</DependentUpon>
</Compile>
<Compile Update="$(MSBuildThisFileDirectory)Issue5354.xaml.cs">
@ -1419,6 +1449,12 @@
<Compile Update="$(MSBuildThisFileDirectory)Issue7593.xaml.cs">
<DependentUpon>Issue7593.xaml</DependentUpon>
</Compile>
<Compile Update="$(MSBuildThisFileDirectory)Issue7758.xaml.cs">
<DependentUpon>Issue7758.xaml</DependentUpon>
</Compile>
<Compile Update="$(MSBuildThisFileDirectory)Issue7943.xaml.cs">
<DependentUpon>Issue7943.xaml</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue1455.xaml">
@ -1480,4 +1516,32 @@
<Generator>MSBuild:Compile</Generator>
</EmbeddedResource>
</ItemGroup>
</Project>
<ItemGroup>
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue7792.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</EmbeddedResource>
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue7758.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue7789.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue7817.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue7943.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</EmbeddedResource>
</ItemGroup>
</Project>

Просмотреть файл

@ -13,7 +13,8 @@
<CollectionView x:Name="CollectionView" Grid.Row="1">
<CollectionView.ItemsLayout>
<GridItemsLayout Span="3" Orientation="Vertical"></GridItemsLayout>
<!--GridItemsLayout Span="3" Orientation="Vertical"></GridItemsLayout>-->
<LinearItemsLayout Orientation="Vertical"></LinearItemsLayout>
</CollectionView.ItemsLayout>
<CollectionView.EmptyView>
No items match your filter.

Просмотреть файл

@ -56,7 +56,7 @@ namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries.GroupingGa
}
));
Add(new Team("Fantastic Four",
Add(new Team("Fantastic Four",
new List<Member>
{
new Member("The Thing"),
@ -66,7 +66,7 @@ namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries.GroupingGa
}
));
Add(new Team("Defenders",
Add(new Team("Defenders",
new List<Member>
{
new Member("Doctor Strange"),
@ -78,8 +78,8 @@ namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries.GroupingGa
new Member("Yellowjacket"),
}
));
Add(new Team("Heroes for Hire",
Add(new Team("Heroes for Hire",
new List<Member>
{
new Member("Luke Cage"),
@ -90,7 +90,7 @@ namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries.GroupingGa
}
));
Add(new Team("West Coast Avengers",
Add(new Team("West Coast Avengers",
new List<Member>
{
new Member("Hawkeye"),
@ -101,7 +101,7 @@ namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries.GroupingGa
}
));
Add(new Team("Great Lakes Avengers",
Add(new Team("Great Lakes Avengers",
new List<Member>
{
new Member("Squirrel Girl"),

Просмотреть файл

@ -30,6 +30,8 @@
new SelectionChangedCommandParameter(), Navigation),
GalleryBuilder.NavButton("Filterable Single Selection", () =>
new FilterSelection(), Navigation),
GalleryBuilder.NavButton("Selection Synchronization", () =>
new SelectionSynchronization(), Navigation),
}
}
};

Просмотреть файл

@ -0,0 +1,90 @@
<?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="Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries.SelectionGalleries.SelectionSynchronization">
<ContentPage.Resources>
<ResourceDictionary>
<DataTemplate x:Key="TestTemplate">
<Label Text="{Binding .}" Margin="0,3,0,3"></Label>
</DataTemplate>
<Style x:Key="CV" TargetType="CollectionView">
<Setter Property="HeightRequest" Value="250"/>
<Setter Property="ItemTemplate" Value="{StaticResource TestTemplate}"></Setter>
<Setter Property="Margin" Value="5,2,5,5"></Setter>
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Content>
<ScrollView>
<StackLayout>
<Label AutomationId="FirstLabel" Text="Set ItemsSource then SelectedItems"/>
<Label Text="Should have items 2 and 3 selected"/>
<CollectionView Style="{StaticResource CV}" SelectionMode="Multiple"
ItemsSource="{Binding Items}" SelectedItems="{Binding SelectedItems}">
</CollectionView>
<Label Text="Set SelectedItems then ItemsSource"/>
<Label Text="Should have items 2 and 3 selected"/>
<CollectionView Style="{StaticResource CV}" SelectionMode="Multiple"
SelectedItems="{Binding SelectedItems}" ItemsSource="{Binding Items}">
</CollectionView>
<Label Text="Set ItemsSource then SelectedItem"/>
<Label Text="Should have item 2 selected"/>
<CollectionView Style="{StaticResource CV}" SelectionMode="Single"
ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}">
</CollectionView>
<Label Text="Set SelectedItem then ItemsSource"/>
<Label Text="Should have item 2 selected"/>
<CollectionView Style="{StaticResource CV}" SelectionMode="Single"
SelectedItem="{Binding SelectedItem}" ItemsSource="{Binding Items}">
</CollectionView>
<Label Text="Set SelectedItems (not in source) then ItemsSource"/>
<Label Text="Should have nothing selected"/>
<CollectionView Style="{StaticResource CV}" SelectionMode="Multiple"
SelectedItems="{Binding SelectedItemsNotInSource}" ItemsSource="{Binding Items}">
</CollectionView>
<Label Text="Set ItemsSource then SelectedItems (not in source)"/>
<Label Text="Should have nothing selected"/>
<CollectionView Style="{StaticResource CV}" SelectionMode="Multiple"
ItemsSource="{Binding Items}" SelectedItems="{Binding SelectedItemsNotInSource}" >
</CollectionView>
<Label Text="Set SelectedItem (not in source) then ItemsSource"/>
<Label Text="Should have nothing selected"/>
<CollectionView Style="{StaticResource CV}" SelectionMode="Single"
SelectedItem="{Binding SelectedItemNotInSource}" ItemsSource="{Binding Items}">
</CollectionView>
<Label Text="Set ItemsSource then SelectedItem (not in source)"/>
<Label Text="Should have nothing selected"/>
<CollectionView Style="{StaticResource CV}" SelectionMode="Single"
ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItemNotInSource}">
</CollectionView>
<Label Text="Switch out ItemSource for one with only some of the SelectedItems"/>
<Button x:Name="SwitchSource" Text="Switch Source" Clicked="SwitchSourceClicked"/>
<Label Text="After hitting the button, should only have Item 3 selected"/>
<CollectionView x:Name="CVSwitchSource" Style="{StaticResource CV}" SelectionMode="Multiple"
ItemsSource="{Binding Items}" SelectedItems="{Binding SelectedItems}">
</CollectionView>
</StackLayout>
</ScrollView>
</ContentPage.Content>
</ContentPage>

Просмотреть файл

@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Internals;
using Xamarin.Forms.Xaml;
namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries.SelectionGalleries
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class SelectionSynchronization : ContentPage
{
public SelectionSynchronization()
{
InitializeComponent();
BindingContext = new SelectionSyncModel();
}
void SwitchSourceClicked(object sender, EventArgs e)
{
var newSource = new List<string> { "Item -1", "Item 0", "Item 1", "Item 3", "Item 4", "Item 5" };
CVSwitchSource.ItemsSource = newSource;
}
}
[Preserve(AllMembers = true)]
public class SelectionSyncModel
{
public SelectionSyncModel()
{
Items = new List<string>() {
"Item 1", "Item 2", "Item 3", "Item 4"
};
SelectedItem = "Item 2";
SelectedItems = new ObservableCollection<object> { "Item 3", "Item 2" };
SelectedItemNotInSource = "Foo";
SelectedItemsNotInSource = new ObservableCollection<object> { "Foo", "Bar", "Baz" };
}
public List<string> Items { get; set; }
public string SelectedItem { get; set; }
public ObservableCollection<object> SelectedItems { get; set; }
public string SelectedItemNotInSource { get; set; }
public ObservableCollection<object> SelectedItemsNotInSource { get; set; }
}
}

Просмотреть файл

@ -174,5 +174,14 @@ namespace Xamarin.Forms.Core.UnitTests
datePicker.SetValue (DatePicker.DateProperty, nullableDateTime);
Assert.AreEqual (dateTime, datePicker.Date);
}
[Test]
//https://github.com/xamarin/Xamarin.Forms/issues/5784
public void SetMaxAndMinDateTimeToNow()
{
var datePicker = new DatePicker();
datePicker.SetValue(DatePicker.MaximumDateProperty, DateTime.Now);
Assert.DoesNotThrow(() => datePicker.SetValue(DatePicker.MinimumDateProperty, DateTime.Now));
}
}
}

Просмотреть файл

@ -243,6 +243,54 @@ namespace Xamarin.Forms
}
}
PropertyInfo GetIndexer(TypeInfo sourceType, string indexerName, string content)
{
if (int.TryParse(content, out _)) { //try to find an indexer taking an int
foreach (var pi in sourceType.DeclaredProperties) {
if (pi.Name != indexerName)
continue;
if (pi.CanRead && pi.GetMethod.GetParameters()[0].ParameterType == typeof(int))
return pi;
if (pi.CanWrite && pi.SetMethod.ReturnType == typeof(int))
return pi;
}
}
//property isn't an int, or there wasn't any int indexer
foreach (var pi in sourceType.DeclaredProperties) {
if (pi.Name != indexerName)
continue;
if (pi.CanRead && pi.GetMethod.GetParameters()[0].ParameterType == typeof(string))
return pi;
if (pi.CanWrite && pi.SetMethod.ReturnType == typeof(string))
return pi;
}
//try to fallback to an object indexer
foreach (var pi in sourceType.DeclaredProperties)
{
if (pi.Name != indexerName)
continue;
if (pi.CanRead && pi.GetMethod.GetParameters()[0].ParameterType == typeof(object))
return pi;
if (pi.CanWrite && pi.SetMethod.ReturnType == typeof(object))
return pi;
}
//defined on an interface ?
foreach (var face in sourceType.ImplementedInterfaces) {
if (GetIndexer(face.GetTypeInfo(), indexerName, content) is PropertyInfo pi)
return pi;
}
//defined on a base class ?
if (sourceType.BaseType is Type baseT && GetIndexer(baseT.GetTypeInfo(), indexerName, content) is PropertyInfo p)
return p;
return null;
}
void SetupPart(TypeInfo sourceType, BindingExpressionPart part)
{
part.Arguments = null;
@ -254,8 +302,7 @@ namespace Xamarin.Forms
{
if (sourceType.IsArray)
{
int index;
if (!int.TryParse(part.Content, out index))
if (!int.TryParse(part.Content, out var index))
Log.Warning("Binding", "{0} could not be parsed as an index for a {1}", part.Content, sourceType);
else
part.Arguments = new object[] { index };
@ -265,46 +312,16 @@ namespace Xamarin.Forms
part.SetterType = sourceType.GetElementType();
}
DefaultMemberAttribute defaultMember = null;
foreach (var attrib in sourceType.GetCustomAttributes(typeof(DefaultMemberAttribute), true))
string indexerName = "Item";
foreach (DefaultMemberAttribute attrib in sourceType.GetCustomAttributes(typeof(DefaultMemberAttribute), true))
{
if (attrib is DefaultMemberAttribute d)
{
defaultMember = d;
break;
}
indexerName = attrib.MemberName;
break;
}
string indexerName = defaultMember != null ? defaultMember.MemberName : "Item";
part.IndexerName = indexerName;
#if NETSTANDARD2_0
try {
property = sourceType.GetDeclaredProperty(indexerName);
}
catch (AmbiguousMatchException) {
// Get most derived instance of property
foreach (var p in sourceType.GetProperties()) {
if (p.Name == indexerName && (property == null || property.DeclaringType.IsAssignableFrom(property.DeclaringType)))
property = p;
}
}
#else
property = sourceType.GetDeclaredProperty(indexerName);
#endif
if (property == null) //is the indexer defined on the base class?
property = sourceType.BaseType.GetProperty(indexerName);
if (property == null) //is the indexer defined on implemented interface ?
{
foreach (var implementedInterface in sourceType.ImplementedInterfaces)
{
property = implementedInterface.GetProperty(indexerName);
if (property != null)
break;
}
}
property = GetIndexer(sourceType, indexerName, part.Content);
if (property != null)
{
@ -312,9 +329,7 @@ namespace Xamarin.Forms
ParameterInfo[] array = property.GetIndexParameters();
if (array.Length > 0)
{
parameter = array[0];
}
if (parameter != null)
{

Просмотреть файл

@ -154,12 +154,12 @@ namespace Xamarin.Forms
static bool ValidateMaximumDate(BindableObject bindable, object value)
{
return (DateTime)value >= ((DatePicker)bindable).MinimumDate;
return ((DateTime)value).Date >= ((DatePicker)bindable).MinimumDate.Date;
}
static bool ValidateMinimumDate(BindableObject bindable, object value)
{
return (DateTime)value <= ((DatePicker)bindable).MaximumDate;
return ((DateTime)value).Date <= ((DatePicker)bindable).MaximumDate.Date;
}
public IPlatformElementConfiguration<T, DatePicker> On<T>() where T : IConfigPlatform

Просмотреть файл

@ -13,7 +13,8 @@ namespace Xamarin.Forms
internal static readonly LinearItemsLayout CarouselDefault = new LinearItemsLayout(ItemsLayoutOrientation.Horizontal)
{
SnapPointsAlignment = SnapPointsAlignment.Center, SnapPointsType = SnapPointsType.Mandatory
SnapPointsType = SnapPointsType.MandatorySingle,
SnapPointsAlignment = SnapPointsAlignment.Center
};
public static readonly BindableProperty ItemSpacingProperty =

Просмотреть файл

@ -50,13 +50,14 @@ namespace Xamarin.Forms.Platform.Android
protected override void UpdateItemsSource()
{
UpdateAdapter();
UpdateEmptyView();
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs changedProperty)
{
if (changedProperty.Is(ItemsView.ItemsSourceProperty))
UpdateItemsSource();
else if (changedProperty.Is(CarouselView.PeekAreaInsetsProperty))
base.OnElementPropertyChanged(sender, changedProperty);
if (changedProperty.Is(CarouselView.PeekAreaInsetsProperty))
UpdatePeekAreaInsets();
else if (changedProperty.Is(CarouselView.IsSwipeEnabledProperty))
UpdateIsSwipeEnabled();

Просмотреть файл

@ -28,7 +28,7 @@ namespace Xamarin.Forms.Platform.Android
public void Stop(Adapter adapter)
{
if (Observing && adapter != null)
if (Observing && adapter != null && adapter.HasObservers)
{
adapter.UnregisterAdapterDataObserver(this);
}

Просмотреть файл

@ -281,7 +281,11 @@ namespace Xamarin.Forms.Platform.Android
if (GetAdapter() != _emptyViewAdapter)
{
_emptyCollectionObserver.Stop(oldItemViewAdapter);
_itemsUpdateScrollObserver.Stop(oldItemViewAdapter);
SetAdapter(null);
SwapAdapter(ItemsViewAdapter, true);
}

Просмотреть файл

@ -349,9 +349,10 @@ namespace Xamarin.Forms.Platform.MacOS
var target = Platform.GetRenderer(page);
var previousPage = _currentStack.Peek().Page;
var previousPageRenderer = CreateViewControllerForPage(previousPage);
ShowView(previousPageRenderer.ViewController);
if (animated)
{
var previousPageRenderer = CreateViewControllerForPage(previousPage);
var transitionStyle = NavigationPage.OnThisPlatform().GetNavigationTransitionPopStyle();
return await this.HandleAsyncAnimation(target.ViewController, previousPageRenderer.ViewController,
@ -382,6 +383,10 @@ namespace Xamarin.Forms.Platform.MacOS
vc.NativeView.WantsLayer = true;
AddChildViewController(vc.ViewController);
View.AddSubview(vc.NativeView);
if (oldPage != null)
{
HideView(Platform.GetRenderer(oldPage)?.ViewController);
}
return true;
}
var vco = Platform.GetRenderer(oldPage);
@ -389,7 +394,23 @@ namespace Xamarin.Forms.Platform.MacOS
var transitionStyle = NavigationPage.OnThisPlatform().GetNavigationTransitionPushStyle();
return await this.HandleAsyncAnimation(vco.ViewController, vc.ViewController,
ToViewControllerTransitionOptions(transitionStyle), () => page?.SendAppearing(), true);
ToViewControllerTransitionOptions(transitionStyle), () =>
{
HideView(vco.ViewController);
page?.SendAppearing();
}, true);
}
void HideView(NSViewController vc)
{
if (vc?.View != null)
vc.View.Hidden = true;
}
void ShowView(NSViewController vc)
{
if (vc?.View != null)
vc.View.Hidden = false;
}
void UpdateBackgroundColor()

Просмотреть файл

@ -12,7 +12,7 @@ using WScrollMode = Windows.UI.Xaml.Controls.ScrollMode;
namespace Xamarin.Forms.Platform.UWP
{
public class CarouselViewRenderer : ItemsViewRenderer
public class CarouselViewRenderer : ItemsViewRenderer<CarouselView>
{
ScrollViewer _scrollViewer;
public CarouselViewRenderer()
@ -20,20 +20,19 @@ namespace Xamarin.Forms.Platform.UWP
CollectionView.VerifyCollectionViewFlagEnabled(nameof(CarouselView));
}
CarouselView CarouselView => (CarouselView)Element;
CarouselView CarouselView => Element;
protected override IItemsLayout Layout => CarouselView?.ItemsLayout;
UWPDataTemplate CarouselItemsViewTemplate => (UWPDataTemplate)UWPApp.Current.Resources["CarouselItemsViewDefaultTemplate"];
LinearItemsLayout CarouselItemsLayout => CarouselView?.ItemsLayout;
double _itemWidth;
double _itemHeight;
UWPDataTemplate CarouselItemsViewTemplate => (UWPDataTemplate)UWPApp.Current.Resources["CarouselItemsViewDefaultTemplate"];
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs changedProperty)
{
base.OnElementPropertyChanged(sender, changedProperty);
if (changedProperty.IsOneOf(ItemsView.ItemsSourceProperty, CarouselView.NumberOfSideItemsProperty, LinearItemsLayout.ItemSpacingProperty))
if (changedProperty.IsOneOf(CarouselView.ItemsSourceProperty, CarouselView.NumberOfSideItemsProperty, LinearItemsLayout.ItemSpacingProperty))
UpdateItemsSource();
else if (changedProperty.Is(ItemsView.ItemTemplateProperty))
else if (changedProperty.Is(CarouselView.ItemTemplateProperty))
UpdateItemTemplate();
else if (changedProperty.Is(CarouselView.PeekAreaInsetsProperty))
UpdatePeekAreaInsets();
@ -43,9 +42,9 @@ namespace Xamarin.Forms.Platform.UWP
UpdateIsBounceEnabled();
}
protected override void HandleLayoutPropertyChange(PropertyChangedEventArgs property)
protected override void HandleLayoutPropertyChanged(PropertyChangedEventArgs property)
{
if (property.IsOneOf(LinearItemsLayout.ItemSpacingProperty, GridItemsLayout.HorizontalItemSpacingProperty, GridItemsLayout.VerticalItemSpacingProperty))
if (property.IsOneOf(LinearItemsLayout.ItemSpacingProperty))
UpdateItemSpacing();
else if (property.Is(ItemsLayout.SnapPointsTypeProperty))
UpdateSnapPointsType();
@ -102,26 +101,14 @@ namespace Xamarin.Forms.Platform.UWP
return new CollectionViewSource
{
Source = TemplatedItemSourceFactory.Create(Element.ItemsSource, Element.ItemTemplate, Element,
_itemHeight, _itemWidth, GetItemSpacing()),
GetItemHeight(), GetItemWidth(), GetItemSpacing()),
IsSourceGrouped = false
};
}
protected override ListViewBase SelectListViewBase()
{
ListViewBase listView = null;
switch (Layout)
{
case LinearItemsLayout listItemsLayout:
listView = CreateCarouselListLayout(listItemsLayout.Orientation);
break;
}
if (listView == null)
{
listView = new FormsListView();
}
ListViewBase listView = CreateCarouselListLayout(CarouselItemsLayout.Orientation);
FindScrollViewer(listView);
@ -148,9 +135,9 @@ namespace Xamarin.Forms.Platform.UWP
void OnListSizeChanged(object sender, Windows.UI.Xaml.SizeChangedEventArgs e)
{
_itemHeight = GetItemHeight();
_itemWidth = GetItemWidth();
UpdateItemsSource();
UpdateSnapPointsType();
UpdateSnapPointsAlignment();
}
void OnScrollViewChanging(object sender, ScrollViewerViewChangingEventArgs e)
@ -175,13 +162,13 @@ namespace Xamarin.Forms.Platform.UWP
ListViewBase.IsSwipeEnabled = CarouselView.IsSwipeEnabled;
switch (Layout)
switch (CarouselItemsLayout.Orientation)
{
case LinearItemsLayout listItemsLayout when listItemsLayout.Orientation == ItemsLayoutOrientation.Horizontal:
case ItemsLayoutOrientation.Horizontal:
ScrollViewer.SetHorizontalScrollMode(ListViewBase, CarouselView.IsSwipeEnabled ? WScrollMode.Auto : WScrollMode.Disabled);
ScrollViewer.SetHorizontalScrollBarVisibility(ListViewBase, CarouselView.IsSwipeEnabled ? WScrollBarVisibility.Auto : WScrollBarVisibility.Disabled);
break;
case LinearItemsLayout listItemsLayout when listItemsLayout.Orientation == ItemsLayoutOrientation.Vertical:
case ItemsLayoutOrientation.Vertical:
ScrollViewer.SetVerticalScrollMode(ListViewBase, CarouselView.IsSwipeEnabled ? WScrollMode.Auto : WScrollMode.Disabled);
ScrollViewer.SetVerticalScrollBarVisibility(ListViewBase, CarouselView.IsSwipeEnabled ? WScrollBarVisibility.Auto : WScrollBarVisibility.Disabled);
break;
@ -198,15 +185,12 @@ namespace Xamarin.Forms.Platform.UWP
{
UpdateItemsSource();
if (Layout is LinearItemsLayout listItemsLayout)
{
var itemSpacing = listItemsLayout.ItemSpacing;
if (listItemsLayout.Orientation == ItemsLayoutOrientation.Horizontal)
_scrollViewer.Padding = new Windows.UI.Xaml.Thickness(0, 0, itemSpacing, 0);
var itemSpacing = CarouselItemsLayout.ItemSpacing;
if (CarouselItemsLayout.Orientation == ItemsLayoutOrientation.Horizontal)
_scrollViewer.Padding = new Windows.UI.Xaml.Thickness(0, 0, itemSpacing, 0);
if (listItemsLayout.Orientation == ItemsLayoutOrientation.Vertical)
_scrollViewer.Padding = new Windows.UI.Xaml.Thickness(0, 0, 0, itemSpacing);
}
if (CarouselItemsLayout.Orientation == ItemsLayoutOrientation.Vertical)
_scrollViewer.Padding = new Windows.UI.Xaml.Thickness(0, 0, 0, itemSpacing);
}
void UpdateSnapPointsType()
@ -214,14 +198,11 @@ namespace Xamarin.Forms.Platform.UWP
if (_scrollViewer == null)
return;
if (Layout is LinearItemsLayout listItemsLayout)
{
if (listItemsLayout.Orientation == ItemsLayoutOrientation.Horizontal)
_scrollViewer.HorizontalSnapPointsType = GetWindowsSnapPointsType(listItemsLayout.SnapPointsType);
if (CarouselItemsLayout.Orientation == ItemsLayoutOrientation.Horizontal)
_scrollViewer.HorizontalSnapPointsType = GetWindowsSnapPointsType(CarouselItemsLayout.SnapPointsType);
if (listItemsLayout.Orientation == ItemsLayoutOrientation.Vertical)
_scrollViewer.VerticalSnapPointsType = GetWindowsSnapPointsType(listItemsLayout.SnapPointsType);
}
if (CarouselItemsLayout.Orientation == ItemsLayoutOrientation.Vertical)
_scrollViewer.VerticalSnapPointsType = GetWindowsSnapPointsType(CarouselItemsLayout.SnapPointsType);
}
void UpdateSnapPointsAlignment()
@ -229,14 +210,11 @@ namespace Xamarin.Forms.Platform.UWP
if (_scrollViewer == null)
return;
if (Layout is LinearItemsLayout listItemsLayout)
{
if (listItemsLayout.Orientation == ItemsLayoutOrientation.Horizontal)
_scrollViewer.HorizontalSnapPointsAlignment = GetWindowsSnapPointsAlignment(listItemsLayout.SnapPointsAlignment);
if (CarouselItemsLayout.Orientation == ItemsLayoutOrientation.Horizontal)
_scrollViewer.HorizontalSnapPointsAlignment = GetWindowsSnapPointsAlignment(CarouselItemsLayout.SnapPointsAlignment);
if (listItemsLayout.Orientation == ItemsLayoutOrientation.Vertical)
_scrollViewer.VerticalSnapPointsAlignment = GetWindowsSnapPointsAlignment(listItemsLayout.SnapPointsAlignment);
}
if (CarouselItemsLayout.Orientation == ItemsLayoutOrientation.Vertical)
_scrollViewer.VerticalSnapPointsAlignment = GetWindowsSnapPointsAlignment(CarouselItemsLayout.SnapPointsAlignment);
}
ListViewBase CreateCarouselListLayout(ItemsLayoutOrientation layoutOrientation)
@ -266,10 +244,10 @@ namespace Xamarin.Forms.Platform.UWP
{
var itemWidth = ActualWidth;
if (Layout is LinearItemsLayout listItemsLayout && listItemsLayout.Orientation == ItemsLayoutOrientation.Horizontal)
if (CarouselItemsLayout.Orientation == ItemsLayoutOrientation.Horizontal)
{
var numberOfVisibleItems = CarouselView.NumberOfSideItems * 2 + 1;
itemWidth = (ActualWidth - CarouselView.PeekAreaInsets.Left - CarouselView.PeekAreaInsets.Right - listItemsLayout.ItemSpacing) / numberOfVisibleItems;
itemWidth = (ActualWidth - CarouselView.PeekAreaInsets.Left - CarouselView.PeekAreaInsets.Right - CarouselItemsLayout.ItemSpacing) / numberOfVisibleItems;
}
return Math.Max(itemWidth, 0);
@ -279,10 +257,10 @@ namespace Xamarin.Forms.Platform.UWP
{
var itemHeight = ActualHeight;
if (Layout is LinearItemsLayout listItemsLayout && listItemsLayout.Orientation == ItemsLayoutOrientation.Vertical)
if (CarouselItemsLayout.Orientation == ItemsLayoutOrientation.Vertical)
{
var numberOfVisibleItems = CarouselView.NumberOfSideItems * 2 + 1;
itemHeight = (ActualHeight - CarouselView.PeekAreaInsets.Top - CarouselView.PeekAreaInsets.Bottom - listItemsLayout.ItemSpacing) / numberOfVisibleItems;
itemHeight = (ActualHeight - CarouselView.PeekAreaInsets.Top - CarouselView.PeekAreaInsets.Bottom - CarouselItemsLayout.ItemSpacing) / numberOfVisibleItems;
}
return Math.Max(itemHeight, 0);
@ -290,16 +268,13 @@ namespace Xamarin.Forms.Platform.UWP
Thickness GetItemSpacing()
{
if (Layout is LinearItemsLayout listItemsLayout)
{
var itemSpacing = listItemsLayout.ItemSpacing;
var itemSpacing = CarouselItemsLayout.ItemSpacing;
if (listItemsLayout.Orientation == ItemsLayoutOrientation.Horizontal)
return new Thickness(itemSpacing, 0, 0, 0);
if (CarouselItemsLayout.Orientation == ItemsLayoutOrientation.Horizontal)
return new Thickness(itemSpacing, 0, 0, 0);
if (listItemsLayout.Orientation == ItemsLayoutOrientation.Vertical)
return new Thickness(0, itemSpacing, 0, 0);
}
if (CarouselItemsLayout.Orientation == ItemsLayoutOrientation.Vertical)
return new Thickness(0, itemSpacing, 0, 0);
return new Thickness(0);
}

Просмотреть файл

@ -14,7 +14,7 @@ using Xamarin.Forms.Platform.UAP;
namespace Xamarin.Forms.Platform.UWP
{
public class CollectionViewRenderer : SelectableItemsViewRenderer
public class CollectionViewRenderer : GroupableItemsViewRenderer<GroupableItemsView>
{
}
}

Просмотреть файл

@ -1,60 +1,68 @@
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using UWPApp = Windows.UI.Xaml.Application;
using UWPControlTemplate = Windows.UI.Xaml.Controls.ControlTemplate;
using UWPControls = Windows.UI.Xaml.Controls;
namespace Xamarin.Forms.Platform.UWP
{
internal class FormsGridView : GridView, IEmptyView
{
int _maximumRowsOrColumns;
int _span;
ItemsWrapGrid _wrapGrid;
ContentControl _emptyViewContentControl;
FrameworkElement _emptyView;
Orientation _orientation;
public FormsGridView()
{
Template = (UWPControlTemplate)UWPApp.Current.Resources["FormsListViewTemplate"];
// Using the full style for this control, because for some reason on 16299 we can't set the ControlTemplate
// (it just fails silently saying it can't find the resource key)
DefaultStyleKey = typeof(FormsGridView);
// TODO hartez 2018/06/06 09:52:16 Do we need to clean this up? If so, where?
RegisterPropertyChangedCallback(ItemsPanelProperty, ItemsPanelChanged);
Loaded += OnLoaded;
}
public int MaximumRowsOrColumns
public int Span
{
get => _maximumRowsOrColumns;
get => _span;
set
{
_maximumRowsOrColumns = value;
_span = value;
if (_wrapGrid != null)
{
_wrapGrid.MaximumRowsOrColumns = MaximumRowsOrColumns;
UpdateItemSize();
}
}
}
public static readonly DependencyProperty EmptyViewVisibilityProperty =
DependencyProperty.Register(nameof(EmptyViewVisibility), typeof(Visibility),
typeof(FormsGridView), new PropertyMetadata(Visibility.Collapsed));
public Visibility EmptyViewVisibility
{
get { return (Visibility)GetValue(EmptyViewVisibilityProperty); }
set { SetValue(EmptyViewVisibilityProperty, value); }
}
public static readonly DependencyProperty EmptyViewVisibilityProperty =
DependencyProperty.Register(nameof(EmptyViewVisibility), typeof(Visibility),
typeof(FormsGridView), new PropertyMetadata(Visibility.Collapsed));
// TODO hartez 2018/06/06 10:01:32 Probably should just create a local enum for this?
public void UseHorizontalItemsPanel()
public Orientation Orientation
{
ItemsPanel =
(ItemsPanelTemplate)UWPApp.Current.Resources["HorizontalGridItemsPanel"];
}
public void UseVerticalItemsPanel()
{
ItemsPanel =
(ItemsPanelTemplate)UWPApp.Current.Resources["VerticalGridItemsPanel"];
get => _orientation;
set
{
_orientation = value;
if (_orientation == Orientation.Horizontal)
{
ItemsPanel = (ItemsPanelTemplate)UWPApp.Current.Resources["HorizontalGridItemsPanel"];
ScrollViewer.SetHorizontalScrollMode(this, ScrollMode.Auto);
ScrollViewer.SetHorizontalScrollBarVisibility(this, UWPControls.ScrollBarVisibility.Auto);
}
else
{
ItemsPanel = (ItemsPanelTemplate)UWPApp.Current.Resources["VerticalGridItemsPanel"];
}
}
}
void FindItemsWrapGrid()
@ -66,7 +74,25 @@ namespace Xamarin.Forms.Platform.UWP
return;
}
_wrapGrid.MaximumRowsOrColumns = MaximumRowsOrColumns;
_wrapGrid.SizeChanged -= WrapGridSizeChanged;
_wrapGrid.SizeChanged += WrapGridSizeChanged;
}
void WrapGridSizeChanged(object sender, SizeChangedEventArgs e)
{
UpdateItemSize();
}
void UpdateItemSize()
{
if (_orientation == Orientation.Horizontal)
{
_wrapGrid.ItemHeight = _wrapGrid.ActualHeight / Span;
}
else
{
_wrapGrid.ItemWidth = _wrapGrid.ActualWidth / Span;
}
}
void ItemsPanelChanged(DependencyObject sender, DependencyProperty dp)
@ -100,5 +126,11 @@ namespace Xamarin.Forms.Platform.UWP
_emptyViewContentControl.Content = _emptyView;
}
}
protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
{
GroupFooterItemTemplateContext.EnsureSelectionDisabled(element, item);
base.PrepareContainerForItemOverride(element, item);
}
}
}
}

Просмотреть файл

@ -15,15 +15,16 @@ namespace Xamarin.Forms.Platform.UWP
Template = (UWPControlTemplate)UWPApp.Current.Resources["FormsListViewTemplate"];
}
public static readonly DependencyProperty EmptyViewVisibilityProperty =
DependencyProperty.Register(nameof(EmptyViewVisibility), typeof(Visibility),
typeof(FormsListView), new PropertyMetadata(Visibility.Collapsed));
public Visibility EmptyViewVisibility
{
get { return (Visibility)GetValue(EmptyViewVisibilityProperty); }
set { SetValue(EmptyViewVisibilityProperty, value); }
}
public static readonly DependencyProperty EmptyViewVisibilityProperty =
DependencyProperty.Register(nameof(EmptyViewVisibility), typeof(Visibility), typeof(FormsListView), new PropertyMetadata(Visibility.Collapsed));
public void SetEmptyView(FrameworkElement emptyView)
{
_emptyView = emptyView;
@ -45,5 +46,11 @@ namespace Xamarin.Forms.Platform.UWP
_emptyViewContentControl.Content = _emptyView;
}
}
protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
{
GroupFooterItemTemplateContext.EnsureSelectionDisabled(element, item);
base.PrepareContainerForItemOverride(element, item);
}
}
}

Просмотреть файл

@ -0,0 +1,23 @@
using Windows.UI.Xaml;
namespace Xamarin.Forms.Platform.UWP
{
internal class GroupFooterItemTemplateContext : ItemTemplateContext
{
public GroupFooterItemTemplateContext(DataTemplate formsDataTemplate, object item,
BindableObject container, double? height = null, double? width = null, Thickness? itemSpacing = null)
: base(formsDataTemplate, item, container, height, width, itemSpacing)
{
}
public static void EnsureSelectionDisabled(DependencyObject element, object item)
{
if (item is GroupFooterItemTemplateContext)
{
// Prevent the group footer from being selectable
(element as FrameworkElement).IsHitTestVisible = false;
}
}
}
}

Просмотреть файл

@ -0,0 +1,17 @@
using Windows.UI.Xaml.Controls;
using UWPApp = Windows.UI.Xaml.Application;
using UWPDataTemplate = Windows.UI.Xaml.DataTemplate;
namespace Xamarin.Forms.Platform.UWP
{
internal class GroupHeaderStyleSelector : GroupStyleSelector
{
protected override GroupStyle SelectGroupStyleCore(object group, uint level)
{
return new GroupStyle
{
HeaderTemplate = (UWPDataTemplate)UWPApp.Current.Resources["GroupHeaderTemplate"]
};
}
}
}

Просмотреть файл

@ -0,0 +1,50 @@
using System.Collections;
using System.Collections.Generic;
namespace Xamarin.Forms.Platform.UWP
{
internal class GroupTemplateContext
{
public ItemTemplateContext HeaderItemTemplateContext { get; }
public ItemTemplateContext FooterItemTemplateContext { get; }
public object Items { get; }
public GroupTemplateContext(ItemTemplateContext headerItemTemplateContext,
ItemTemplateContext footerItemTemplateContext, object items)
{
HeaderItemTemplateContext = headerItemTemplateContext;
FooterItemTemplateContext = footerItemTemplateContext;
if (footerItemTemplateContext == null)
{
Items = items;
}
else
{
// UWP ListViewBase does not support group footers. So we're going to fake the footer by adding an
// extra item to the ItemsSource so the footer shows up at the end of the group.
if (items is IList itemsList)
{
// If it's already an IList, we want to make sure to keep it that way
itemsList.Add(footerItemTemplateContext);
Items = itemsList;
return;
}
// If the group items are not an IList, then we'll have to append the footer the hard way
var listPlusFooter = new List<object>();
foreach (var item in (items as IEnumerable))
{
listPlusFooter.Add(item);
}
listPlusFooter.Add(footerItemTemplateContext);
Items = listPlusFooter;
}
}
}
}

Просмотреть файл

@ -0,0 +1,49 @@
using System.ComponentModel;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Data;
namespace Xamarin.Forms.Platform.UWP
{
public class GroupableItemsViewRenderer<TItemsView> : SelectableItemsViewRenderer<TItemsView>
where TItemsView : GroupableItemsView
{
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs changedProperty)
{
base.OnElementPropertyChanged(sender, changedProperty);
if (changedProperty.IsOneOf(GroupableItemsView.IsGroupedProperty,
GroupableItemsView.GroupFooterTemplateProperty, GroupableItemsView.GroupHeaderTemplateProperty))
{
UpdateItemsSource();
}
}
protected override CollectionViewSource CreateCollectionViewSource()
{
if (ItemsView != null && ItemsView.IsGrouped)
{
var itemTemplate = Element.ItemTemplate;
var itemsSource = Element.ItemsSource;
return new CollectionViewSource
{
Source = TemplatedItemSourceFactory.CreateGrouped(itemsSource, itemTemplate,
ItemsView.GroupHeaderTemplate, ItemsView.GroupFooterTemplate, Element),
IsSourceGrouped = true,
ItemsPath = new Windows.UI.Xaml.PropertyPath(nameof(GroupTemplateContext.Items))
};
}
else
{
return base.CreateCollectionViewSource();
}
}
protected override void UpdateItemTemplate()
{
base.UpdateItemTemplate();
ListViewBase.GroupStyleSelector = new GroupHeaderStyleSelector();
}
}
}

Просмотреть файл

@ -0,0 +1,166 @@
using System.Collections;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
namespace Xamarin.Forms.Platform.UWP
{
internal class GroupedItemTemplateCollection : ObservableCollection<GroupTemplateContext>
{
readonly IEnumerable _itemsSource;
readonly DataTemplate _itemTemplate;
readonly DataTemplate _groupHeaderTemplate;
readonly DataTemplate _groupFooterTemplate;
readonly BindableObject _container;
readonly IList _groupList;
public GroupedItemTemplateCollection(IEnumerable itemsSource, DataTemplate itemTemplate,
DataTemplate groupHeaderTemplate, DataTemplate groupFooterTemplate, BindableObject container)
{
_itemsSource = itemsSource;
_itemTemplate = itemTemplate;
_groupHeaderTemplate = groupHeaderTemplate;
_groupFooterTemplate = groupFooterTemplate;
_container = container;
foreach (var group in _itemsSource)
{
var groupTemplateContext = CreateGroupTemplateContext(group);
Add(groupTemplateContext);
}
if (_itemsSource is IList groupList && _itemsSource is INotifyCollectionChanged incc)
{
_groupList = groupList;
incc.CollectionChanged += GroupsChanged;
}
}
GroupTemplateContext CreateGroupTemplateContext(object group)
{
var groupHeaderTemplateContext = _groupHeaderTemplate != null
? new ItemTemplateContext(_groupHeaderTemplate, group, _container) : null;
var groupFooterTemplateContext = _groupFooterTemplate != null
? new GroupFooterItemTemplateContext(_groupFooterTemplate, group, _container) : null;
// This is where we'll eventually look at GroupItemPropertyName
var groupItemsList = TemplatedItemSourceFactory.Create(group as IEnumerable, _itemTemplate, _container);
return new GroupTemplateContext(groupHeaderTemplateContext, groupFooterTemplateContext, groupItemsList);
}
void GroupsChanged(object sender, NotifyCollectionChangedEventArgs args)
{
switch (args.Action)
{
case NotifyCollectionChangedAction.Add:
Add(args);
break;
case NotifyCollectionChangedAction.Move:
Move(args);
break;
case NotifyCollectionChangedAction.Remove:
Remove(args);
break;
case NotifyCollectionChangedAction.Replace:
Replace(args);
break;
case NotifyCollectionChangedAction.Reset:
Reset();
break;
}
}
void Add(NotifyCollectionChangedEventArgs args)
{
var startIndex = args.NewStartingIndex > -1 ? args.NewStartingIndex : _groupList.IndexOf(args.NewItems[0]);
var count = args.NewItems.Count;
for (int n = 0; n < count; n++)
{
Insert(startIndex, CreateGroupTemplateContext(args.NewItems[n]));
}
}
void Move(NotifyCollectionChangedEventArgs args)
{
var count = args.NewItems.Count;
if (args.OldStartingIndex > args.NewStartingIndex)
{
for (int n = 0; n < count; n++)
{
Move(args.OldStartingIndex + n, args.NewStartingIndex + n);
}
return;
}
for (int n = count - 1; n >= 0; n--)
{
Move(args.OldStartingIndex + n, args.NewStartingIndex + n);
}
}
void Remove(NotifyCollectionChangedEventArgs args)
{
var startIndex = args.OldStartingIndex;
if (startIndex < 0)
{
// INCC implementation isn't giving us enough information to know where the removed items were in the
// collection. So the best we can do is a full Reset.
Reset();
return;
}
var count = args.OldItems.Count;
for (int n = startIndex + count - 1; n >= startIndex; n--)
{
RemoveAt(n);
}
}
void Replace(NotifyCollectionChangedEventArgs args)
{
var newItemCount = args.NewItems.Count;
if (newItemCount == args.OldItems.Count)
{
for (int n = 0; n < newItemCount; n++)
{
var index = args.OldStartingIndex + n;
var oldItem = this[index];
var newItem = CreateGroupTemplateContext(args.NewItems[0]);
Items[index] = newItem;
var update = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, newItem, oldItem, index);
OnCollectionChanged(update);
}
}
else
{
// If we're replacing one set with an equal size set, we can do a soft reset; if not, we have to completely
// rebuild the collection
Reset();
}
}
void Reset()
{
Items.Clear();
_groupList.Clear();
foreach (var group in _itemsSource)
{
var groupTemplateContext = CreateGroupTemplateContext(group);
_groupList.Add(group);
Items.Add(groupTemplateContext);
}
var reset = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset);
OnCollectionChanged(reset);
}
}
}

Просмотреть файл

@ -1,7 +1,9 @@
using Windows.UI.Xaml;
using System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Xamarin.Forms.Internals;
using WThickness = Windows.UI.Xaml.Thickness;
using WSize = Windows.Foundation.Size;
namespace Xamarin.Forms.Platform.UWP
{
@ -148,39 +150,54 @@ namespace Xamarin.Forms.Platform.UWP
InvalidateMeasure();
}
protected override Windows.Foundation.Size MeasureOverride(Windows.Foundation.Size availableSize)
protected override WSize MeasureOverride(WSize availableSize)
{
if (_renderer == null)
{
return base.MeasureOverride(availableSize);
}
var frameworkElement = Content as FrameworkElement;
var formsElement = _renderer.Element;
if (ItemHeight != default || ItemWidth != default)
{
formsElement.Layout(new Rectangle(0, 0, ItemWidth, ItemHeight));
var wsize = new Windows.Foundation.Size(ItemWidth, ItemHeight);
var wsize = new WSize(ItemWidth, ItemHeight);
(Content as FrameworkElement).Margin = new WThickness(ItemSpacing.Left, ItemSpacing.Top, ItemSpacing.Right, ItemSpacing.Bottom);
frameworkElement.Margin = new WThickness(ItemSpacing.Left, ItemSpacing.Top, ItemSpacing.Right, ItemSpacing.Bottom);
(Content as FrameworkElement).Measure(wsize);
frameworkElement.Measure(wsize);
return base.MeasureOverride(wsize);
}
else
{
Size request = formsElement.Measure(availableSize.Width, availableSize.Height,
MeasureFlags.IncludeMargins).Request;
var (width, height) = formsElement.Measure(availableSize.Width, availableSize.Height,
MeasureFlags.IncludeMargins).Request;
formsElement.Layout(new Rectangle(0, 0, request.Width, request.Height));
width = Max(width, availableSize.Width);
height = Max(height, availableSize.Height);
var wsize = new Windows.Foundation.Size(request.Width, request.Height);
formsElement.Layout(new Rectangle(0, 0, width, height));
(Content as FrameworkElement).Measure(wsize);
var wsize = new WSize(width, height);
frameworkElement.Measure(wsize);
return base.MeasureOverride(wsize);
}
}
double Max(double requested, double available)
{
return Math.Max(requested, ClampInfinity(available));
}
double ClampInfinity(double value)
{
return double.IsInfinity(value) ? 0 : value;
}
}
}

Просмотреть файл

@ -2,6 +2,13 @@
{
internal class ItemTemplateContext
{
public DataTemplate FormsDataTemplate { get; }
public object Item { get; }
public BindableObject Container { get; }
public double ItemHeight { get; }
public double ItemWidth { get; }
public Thickness ItemSpacing { get; }
public ItemTemplateContext(DataTemplate formsDataTemplate, object item, BindableObject container,
double? height = null, double? width = null, Thickness? itemSpacing = null)
{
@ -18,12 +25,5 @@
if (itemSpacing.HasValue)
ItemSpacing = itemSpacing.Value;
}
public DataTemplate FormsDataTemplate { get; }
public object Item { get; }
public BindableObject Container { get; }
public double ItemHeight { get; }
public double ItemWidth { get; }
public Thickness ItemSpacing { get; }
}
}

Просмотреть файл

@ -67,7 +67,7 @@ namespace Xamarin.Forms.Platform.UWP
internal class ItemTemplateContextListEnumerator : IEnumerator<ItemTemplateContext>
{
public ItemTemplateContext Current { get; private set; }
object IEnumerator.Current { get; }
object IEnumerator.Current => Current;
int _currentIndex = -1;
private ItemTemplateContextList _itemTemplateContextList;

Просмотреть файл

@ -1,16 +1,9 @@
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using System.ComponentModel;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Xamarin.Forms.Internals;
using Xamarin.Forms.Platform.UAP;
using UwpScrollBarVisibility = Windows.UI.Xaml.Controls.ScrollBarVisibility;
using UWPApp = Windows.UI.Xaml.Application;
using UWPDataTemplate = Windows.UI.Xaml.DataTemplate;
@ -18,7 +11,8 @@ using System.Collections.Specialized;
namespace Xamarin.Forms.Platform.UWP
{
public abstract class ItemsViewRenderer : ViewRenderer<ItemsView, ListViewBase>
public abstract class ItemsViewRenderer<TItemsView> : ViewRenderer<TItemsView, ListViewBase>
where TItemsView : ItemsView
{
protected CollectionViewSource CollectionViewSource;
@ -32,9 +26,10 @@ namespace Xamarin.Forms.Platform.UWP
FrameworkElement _emptyView;
View _formsEmptyView;
protected TItemsView ItemsView => Element;
protected ItemsControl ItemsControl { get; private set; }
protected override void OnElementChanged(ElementChangedEventArgs<ItemsView> args)
protected override void OnElementChanged(ElementChangedEventArgs<TItemsView> args)
{
base.OnElementChanged(args);
TearDownOldElement(args.OldElement);
@ -45,30 +40,31 @@ namespace Xamarin.Forms.Platform.UWP
{
base.OnElementPropertyChanged(sender, changedProperty);
if (changedProperty.Is(ItemsView.ItemsSourceProperty))
if (changedProperty.Is(Xamarin.Forms.ItemsView.ItemsSourceProperty))
{
UpdateItemsSource();
}
else if (changedProperty.Is(ItemsView.ItemTemplateProperty))
else if (changedProperty.Is(Xamarin.Forms.ItemsView.ItemTemplateProperty))
{
UpdateItemTemplate();
}
else if (changedProperty.Is(ItemsView.HorizontalScrollBarVisibilityProperty))
else if (changedProperty.Is(Xamarin.Forms.ItemsView.HorizontalScrollBarVisibilityProperty))
{
UpdateHorizontalScrollBarVisibility();
}
else if (changedProperty.Is(ItemsView.VerticalScrollBarVisibilityProperty))
else if (changedProperty.Is(Xamarin.Forms.ItemsView.VerticalScrollBarVisibilityProperty))
{
UpdateVerticalScrollBarVisibility();
}
else if (changedProperty.IsOneOf(ItemsView.EmptyViewProperty, ItemsView.EmptyViewTemplateProperty))
else if (changedProperty.IsOneOf(Xamarin.Forms.ItemsView.EmptyViewProperty,
Xamarin.Forms.ItemsView.EmptyViewTemplateProperty))
{
UpdateEmptyView();
}
}
protected abstract ListViewBase SelectListViewBase();
protected abstract void HandleLayoutPropertyChange(PropertyChangedEventArgs property);
protected abstract void HandleLayoutPropertyChanged(PropertyChangedEventArgs property);
protected abstract IItemsLayout Layout { get; }
protected virtual void UpdateItemsSource()
@ -78,7 +74,6 @@ namespace Xamarin.Forms.Platform.UWP
return;
}
// TODO hartez 2018-05-22 12:59 PM Handle grouping
CleanUpCollectionViewSource();
@ -109,7 +104,7 @@ namespace Xamarin.Forms.Platform.UWP
}
}
if (Element.ItemsSource == null)
if (Element?.ItemsSource == null)
{
if (CollectionViewSource?.Source is INotifyCollectionChanged incc)
{
@ -167,7 +162,7 @@ namespace Xamarin.Forms.Platform.UWP
void LayoutPropertyChanged(object sender, PropertyChangedEventArgs property)
{
HandleLayoutPropertyChange(property);
HandleLayoutPropertyChanged(property);
}
protected virtual void SetUpNewElement(ItemsView newElement)
@ -213,16 +208,15 @@ namespace Xamarin.Forms.Platform.UWP
// Stop listening for ScrollTo requests
oldElement.ScrollToRequested -= ScrollToRequested;
if (CollectionViewSource != null)
{
CleanUpCollectionViewSource();
}
if (ListViewBase != null)
{
ListViewBase.ItemsSource = null;
}
if (CollectionViewSource != null)
{
CollectionViewSource.Source = null;
}
}
void UpdateVerticalScrollBarVisibility()

Просмотреть файл

@ -2,10 +2,10 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Xamarin.Forms.Platform.UWP">
<ItemsPanelTemplate x:Key="HorizontalListItemsPanel">
<ItemsStackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
<ItemsPanelTemplate x:Key="HorizontalListItemsPanel">
<ItemsStackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
<ItemsPanelTemplate x:Key="HorizontalGridItemsPanel">
<!-- Yes, this is counterintuitive. Orientation here means "direction we lay out the items until we hit the
@ -27,6 +27,14 @@
</local:ItemContentControl>
</DataTemplate>
<DataTemplate x:Key="GroupHeaderTemplate">
<local:ItemContentControl
x:Name="ItemContentControl" DataContext="{Binding HeaderItemTemplateContext}"
FormsDataTemplate="{Binding FormsDataTemplate}" FormsDataContext="{Binding Item}"
FormsContainer="{Binding Container}">
</local:ItemContentControl>
</DataTemplate>
<DataTemplate x:Key="CarouselItemsViewDefaultTemplate">
<local:ItemContentControl
x:Name="ItemContentControl"
@ -79,35 +87,77 @@
</Border>
</ControlTemplate>
<ControlTemplate x:Key="FormsGridViewTemplate" TargetType="local:FormsGridView">
<Border BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<ContentControl x:Name="EmptyViewContentControl" Visibility="{TemplateBinding EmptyViewVisibility}"></ContentControl>
<ScrollViewer x:Name="ScrollViewer"
TabNavigation="{TemplateBinding TabNavigation}"
HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}"
HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
IsHorizontalScrollChainingEnabled="{TemplateBinding ScrollViewer.IsHorizontalScrollChainingEnabled}"
VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}"
VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"
IsVerticalScrollChainingEnabled="{TemplateBinding ScrollViewer.IsVerticalScrollChainingEnabled}"
IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}"
IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}"
ZoomMode="{TemplateBinding ScrollViewer.ZoomMode}"
IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}"
BringIntoViewOnFocusChange="{TemplateBinding ScrollViewer.BringIntoViewOnFocusChange}"
AutomationProperties.AccessibilityView="Raw">
<ItemsPresenter Header="{TemplateBinding Header}"
HeaderTemplate="{TemplateBinding HeaderTemplate}"
HeaderTransitions="{TemplateBinding HeaderTransitions}"
Footer="{TemplateBinding Footer}"
FooterTemplate="{TemplateBinding FooterTemplate}"
FooterTransitions="{TemplateBinding FooterTransitions}"
Padding="{TemplateBinding Padding}" />
</ScrollViewer>
</Grid>
</Border>
</ControlTemplate>
<!-- We much rather just use a ControlTemplate for this the way we do with FormsListView, but unfortunately
16299 (and presumably lower) can't find and set the control template. So we use the entire style instead. If we
get to a point where we don't have to support these earlier versions, we can replace this style with just the
template. (See also FormsGridView.cs) -->
<Style TargetType="local:FormsGridView">
<Setter Property="Padding" Value="0,0,0,10" />
<Setter Property="IsTabStop" Value="False" />
<Setter Property="TabNavigation" Value="Once" />
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled" />
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto" />
<Setter Property="ScrollViewer.HorizontalScrollMode" Value="Disabled" />
<Setter Property="ScrollViewer.IsHorizontalRailEnabled" Value="False" />
<Setter Property="ScrollViewer.VerticalScrollMode" Value="Enabled" />
<Setter Property="ScrollViewer.IsVerticalRailEnabled" Value="True" />
<Setter Property="ScrollViewer.ZoomMode" Value="Disabled" />
<Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="False" />
<Setter Property="ScrollViewer.BringIntoViewOnFocusChange" Value="True" />
<Setter Property="IsSwipeEnabled" Value="True" />
<Setter Property="UseSystemFocusVisuals" Value="True" />
<Setter Property="FocusVisualMargin" Value="-2" />
<Setter Property="ItemContainerTransitions">
<Setter.Value>
<TransitionCollection>
<AddDeleteThemeTransition />
<ContentThemeTransition />
<ReorderThemeTransition />
<EntranceThemeTransition IsStaggeringEnabled="False" />
</TransitionCollection>
</Setter.Value>
</Setter>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<ItemsWrapGrid Orientation="Horizontal" />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:FormsGridView">
<Border BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<ContentControl x:Name="EmptyViewContentControl" Visibility="{TemplateBinding EmptyViewVisibility}"></ContentControl>
<ScrollViewer x:Name="ScrollViewer"
TabNavigation="{TemplateBinding TabNavigation}"
HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}"
HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
IsHorizontalScrollChainingEnabled="{TemplateBinding ScrollViewer.IsHorizontalScrollChainingEnabled}"
VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}"
VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"
IsVerticalScrollChainingEnabled="{TemplateBinding ScrollViewer.IsVerticalScrollChainingEnabled}"
IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}"
IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}"
ZoomMode="{TemplateBinding ScrollViewer.ZoomMode}"
IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}"
BringIntoViewOnFocusChange="{TemplateBinding ScrollViewer.BringIntoViewOnFocusChange}"
AutomationProperties.AccessibilityView="Raw">
<ItemsPresenter Header="{TemplateBinding Header}"
HeaderTemplate="{TemplateBinding HeaderTemplate}"
HeaderTransitions="{TemplateBinding HeaderTransitions}"
Footer="{TemplateBinding Footer}"
FooterTemplate="{TemplateBinding FooterTemplate}"
FooterTransitions="{TemplateBinding FooterTransitions}"
Padding="{TemplateBinding Padding}" />
</ScrollViewer>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="HorizontalCarouselListStyle" TargetType="local:FormsListView">
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Hidden" />
@ -142,5 +192,61 @@
</Setter>
</Style>
<!-- Custom version of the style which removes the horizontal rule below the header -->
<Style TargetType="ListViewHeaderItem">
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
<Setter Property="FontSize" Value="{ThemeResource ListViewHeaderItemThemeFontSize}" />
<Setter Property="Background" Value="{ThemeResource ListViewHeaderItemBackground}" />
<Setter Property="Margin" Value="0,0,0,4" />
<Setter Property="Padding" Value="12,8,12,0" />
<Setter Property="HorizontalContentAlignment" Value="Left" />
<Setter Property="VerticalContentAlignment" Value="Top" />
<Setter Property="MinHeight" Value="{ThemeResource ListViewHeaderItemMinHeight}" />
<Setter Property="UseSystemFocusVisuals" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewHeaderItem">
<StackPanel Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
<ContentPresenter x:Name="ContentPresenter"
Margin="{TemplateBinding Padding}"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
ContentTransitions="{TemplateBinding ContentTransitions}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" />
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Custom version of the style which removes the horizontal rule below the header -->
<Style TargetType="GridViewHeaderItem">
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
<Setter Property="FontSize" Value="{ThemeResource GridViewHeaderItemThemeFontSize}" />
<Setter Property="Background" Value="{ThemeResource GridViewHeaderItemBackground}" />
<Setter Property="Margin" Value="0,0,0,4" />
<Setter Property="Padding" Value="12,8,12,0" />
<Setter Property="HorizontalContentAlignment" Value="Left" />
<Setter Property="VerticalContentAlignment" Value="Top" />
<Setter Property="MinHeight" Value="{ThemeResource GridViewHeaderItemMinHeight}" />
<Setter Property="UseSystemFocusVisuals" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="GridViewHeaderItem">
<StackPanel Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
<ContentPresenter x:Name="ContentPresenter"
Margin="{TemplateBinding Padding}"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
ContentTransitions="{TemplateBinding ContentTransitions}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" />
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

Просмотреть файл

@ -5,9 +5,9 @@ using UWPListViewSelectionMode = Windows.UI.Xaml.Controls.ListViewSelectionMode;
namespace Xamarin.Forms.Platform.UWP
{
public class SelectableItemsViewRenderer : StructuredItemsViewRenderer
public class SelectableItemsViewRenderer<TItemsView> : StructuredItemsViewRenderer<TItemsView>
where TItemsView : SelectableItemsView
{
SelectableItemsView _selectableItemsView;
bool _ignoreNativeSelectionChange;
protected override void TearDownOldElement(ItemsView oldElement)
@ -19,9 +19,9 @@ namespace Xamarin.Forms.Platform.UWP
oldListViewBase.SelectionChanged -= OnNativeSelectionChanged;
}
if (_selectableItemsView != null)
if (ItemsView != null)
{
_selectableItemsView.SelectionChanged -= OnSelectionChanged;
ItemsView.SelectionChanged -= OnSelectionChanged;
}
base.TearDownOldElement(oldElement);
@ -36,11 +36,9 @@ namespace Xamarin.Forms.Platform.UWP
return;
}
_selectableItemsView = newElement as SelectableItemsView;
if (_selectableItemsView != null)
if (ItemsView != null)
{
_selectableItemsView.SelectionChanged += OnSelectionChanged;
ItemsView.SelectionChanged += OnSelectionChanged;
}
var newListViewBase = ListViewBase;
@ -50,7 +48,7 @@ namespace Xamarin.Forms.Platform.UWP
newListViewBase.SetBinding(ListViewBase.SelectionModeProperty,
new Windows.UI.Xaml.Data.Binding
{
Source = _selectableItemsView,
Source = ItemsView,
Path = new Windows.UI.Xaml.PropertyPath("SelectionMode"),
Converter = new SelectionModeConvert(),
Mode = Windows.UI.Xaml.Data.BindingMode.TwoWay
@ -67,6 +65,7 @@ namespace Xamarin.Forms.Platform.UWP
_ignoreNativeSelectionChange = true;
base.UpdateItemsSource();
UpdateNativeSelection();
_ignoreNativeSelectionChange = false;
}
@ -80,24 +79,24 @@ namespace Xamarin.Forms.Platform.UWP
case UWPListViewSelectionMode.None:
break;
case UWPListViewSelectionMode.Single:
if (_selectableItemsView != null)
if (ItemsView != null)
{
if (_selectableItemsView.SelectedItem == null)
if (ItemsView.SelectedItem == null)
{
ListViewBase.SelectedItem = null;
}
else
{
ListViewBase.SelectedItem =
ListViewBase.Items.First(item =>
ListViewBase.Items.FirstOrDefault(item =>
{
if (item is ItemTemplateContext itemPair)
{
return itemPair.Item == _selectableItemsView.SelectedItem;
return itemPair.Item == ItemsView.SelectedItem;
}
else
{
return item == _selectableItemsView.SelectedItem;
return item == ItemsView.SelectedItem;
}
});
}
@ -108,11 +107,11 @@ namespace Xamarin.Forms.Platform.UWP
ListViewBase.SelectedItems.Clear();
foreach (var nativeItem in ListViewBase.Items)
{
if (nativeItem is ItemTemplateContext itemPair && _selectableItemsView.SelectedItems.Contains(itemPair.Item))
if (nativeItem is ItemTemplateContext itemPair && ItemsView.SelectedItems.Contains(itemPair.Item))
{
ListViewBase.SelectedItems.Add(nativeItem);
}
else if (_selectableItemsView.SelectedItems.Contains(nativeItem))
else if (ItemsView.SelectedItems.Contains(nativeItem))
{
ListViewBase.SelectedItems.Add(nativeItem);
}
@ -155,7 +154,7 @@ namespace Xamarin.Forms.Platform.UWP
case UWPListViewSelectionMode.Multiple:
selectableItemsView.SelectionChanged -= OnSelectionChanged;
_selectableItemsView.SelectedItems.Clear();
ItemsView.SelectedItems.Clear();
var selectedItems =
ListViewBase.SelectedItems
.Select(a =>
@ -167,7 +166,7 @@ namespace Xamarin.Forms.Platform.UWP
foreach (var item in selectedItems)
{
_selectableItemsView.SelectedItems.Add(item);
ItemsView.SelectedItems.Add(item);
}
selectableItemsView.SelectionChanged += OnSelectionChanged;

Просмотреть файл

@ -1,22 +1,21 @@
using System.ComponentModel;
using Windows.UI.Xaml.Controls;
using UWPApp = Windows.UI.Xaml.Application;
using Xamarin.Forms.Platform.UAP;
using WScrollMode = Windows.UI.Xaml.Controls.ScrollMode;
namespace Xamarin.Forms.Platform.UWP
{
public class StructuredItemsViewRenderer : ItemsViewRenderer
public class StructuredItemsViewRenderer<TItemsView> : ItemsViewRenderer<TItemsView>
where TItemsView : StructuredItemsView
{
StructuredItemsView _structuredItemsView;
View _currentHeader;
View _currentFooter;
protected override IItemsLayout Layout { get => _structuredItemsView.ItemsLayout; }
protected override IItemsLayout Layout { get => ItemsView?.ItemsLayout; }
protected override void SetUpNewElement(ItemsView newElement)
{
_structuredItemsView = newElement as StructuredItemsView;
base.SetUpNewElement(newElement);
if (newElement == null)
@ -70,7 +69,7 @@ namespace Xamarin.Forms.Platform.UWP
_currentHeader = null;
}
var header = _structuredItemsView.Header;
var header = ItemsView.Header;
switch (header)
{
@ -91,7 +90,7 @@ namespace Xamarin.Forms.Platform.UWP
break;
default:
var headerTemplate = _structuredItemsView.HeaderTemplate;
var headerTemplate = ItemsView.HeaderTemplate;
if (headerTemplate != null)
{
ListViewBase.HeaderTemplate = ItemsViewTemplate;
@ -119,7 +118,7 @@ namespace Xamarin.Forms.Platform.UWP
_currentFooter = null;
}
var footer = _structuredItemsView.Footer;
var footer = ItemsView.Footer;
switch (footer)
{
@ -140,7 +139,7 @@ namespace Xamarin.Forms.Platform.UWP
break;
default:
var footerTemplate = _structuredItemsView.FooterTemplate;
var footerTemplate = ItemsView.FooterTemplate;
if (footerTemplate != null)
{
ListViewBase.FooterTemplate = ItemsViewTemplate;
@ -155,48 +154,35 @@ namespace Xamarin.Forms.Platform.UWP
}
}
protected override void HandleLayoutPropertyChange(PropertyChangedEventArgs property)
protected override void HandleLayoutPropertyChanged(PropertyChangedEventArgs property)
{
if (property.Is(GridItemsLayout.SpanProperty))
{
if (ListViewBase is FormsGridView formsGridView)
{
formsGridView.MaximumRowsOrColumns = ((GridItemsLayout)Layout).Span;
formsGridView.Span = ((GridItemsLayout)Layout).Span;
}
}
}
static ListViewBase CreateGridView(GridItemsLayout gridItemsLayout)
{
var gridView = new FormsGridView();
if (gridItemsLayout.Orientation == ItemsLayoutOrientation.Horizontal)
return new FormsGridView
{
gridView.UseHorizontalItemsPanel();
Orientation = gridItemsLayout.Orientation == ItemsLayoutOrientation.Horizontal
? Orientation.Horizontal
: Orientation.Vertical,
// TODO hartez 2018/06/06 12:13:38 Should this logic just be built into FormsGridView?
ScrollViewer.SetHorizontalScrollMode(gridView, WScrollMode.Auto);
ScrollViewer.SetHorizontalScrollBarVisibility(gridView,
Windows.UI.Xaml.Controls.ScrollBarVisibility.Auto);
}
else
{
gridView.UseVerticalItemsPanel();
}
gridView.MaximumRowsOrColumns = gridItemsLayout.Span;
return gridView;
Span = gridItemsLayout.Span
};
}
static ListViewBase CreateHorizontalListView()
{
// TODO hartez 2018/06/05 16:18:57 Is there any performance benefit to caching the ItemsPanelTemplate lookup?
// TODO hartez 2018/05/29 15:38:04 Make sure the ItemsViewStyles.xaml xbf gets into the nuspec
var horizontalListView = new Windows.UI.Xaml.Controls.ListView()
{
ItemsPanel =
(ItemsPanelTemplate)Windows.UI.Xaml.Application.Current.Resources["HorizontalListItemsPanel"]
(ItemsPanelTemplate)UWPApp.Current.Resources["HorizontalListItemsPanel"]
};
ScrollViewer.SetHorizontalScrollMode(horizontalListView, WScrollMode.Auto);

Просмотреть файл

@ -5,7 +5,8 @@ namespace Xamarin.Forms.Platform.UWP
{
internal static class TemplatedItemSourceFactory
{
internal static object Create(IEnumerable itemsSource, DataTemplate itemTemplate, BindableObject container, double? itemHeight = null, double? itemWidth = null, Thickness? itemSpacing = null)
internal static object Create(IEnumerable itemsSource, DataTemplate itemTemplate, BindableObject container,
double? itemHeight = null, double? itemWidth = null, Thickness? itemSpacing = null)
{
switch (itemsSource)
{
@ -17,5 +18,11 @@ namespace Xamarin.Forms.Platform.UWP
return new ItemTemplateContextEnumerable(itemsSource, itemTemplate, container, itemHeight, itemWidth, itemSpacing);
}
internal static object CreateGrouped(IEnumerable itemsSource, DataTemplate itemTemplate,
DataTemplate groupHeaderTemplate, DataTemplate groupFooterTemplate, BindableObject container)
{
return new GroupedItemTemplateCollection(itemsSource, itemTemplate, groupHeaderTemplate, groupFooterTemplate, container);
}
}
}

Просмотреть файл

@ -13,7 +13,7 @@
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
<TargetPlatformVersion>10.0.16299.0</TargetPlatformVersion>
<TargetPlatformMinVersion>10.0.16299.0</TargetPlatformMinVersion>
<SkipMicrosoftUIXamlCheckTargetPlatformVersion>true</SkipMicrosoftUIXamlCheckTargetPlatformVersion>
<SkipMicrosoftUIXamlCheckTargetPlatformVersion>true</SkipMicrosoftUIXamlCheckTargetPlatformVersion>
<MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
@ -47,6 +47,11 @@
<Compile Include="CollectionView\ItemsViewRenderer.cs" />
<Compile Include="CollectionView\ItemTemplateContextList.cs" />
<Compile Include="CollectionView\ScrollHelpers.cs" />
<Compile Include="CollectionView\GroupedItemTemplateCollection.cs" />
<Compile Include="CollectionView\GroupFooterItemTemplateContext.cs" />
<Compile Include="CollectionView\GroupHeaderStyleSelector.cs" />
<Compile Include="CollectionView\GroupTemplateContext.cs" />
<Compile Include="CollectionView\GroupableItemsViewRenderer.cs" />
<Compile Include="CollectionView\SelectableItemsViewRenderer.cs" />
<Compile Include="CollectionView\StructuredItemsViewRenderer.cs" />
<Compile Include="ColorExtensions.cs" />
@ -213,6 +218,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="CollectionView\ItemsViewStyles.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="FormsCheckBoxStyle.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
@ -234,10 +243,6 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="CollectionView\ItemsViewStyles.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="MasterDetailControlStyle.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>

Просмотреть файл

@ -7,21 +7,23 @@ using UIKit;
namespace Xamarin.Forms.Platform.iOS
{
public class CarouselViewController : ItemsViewController
public class CarouselViewController : ItemsViewController<CarouselView>
{
CarouselView _carouselView;
ItemsViewLayout _layout;
bool _viewInitialized;
public CarouselViewController(CarouselView itemsView, ItemsViewLayout layout) : base(itemsView, layout)
{
_carouselView = itemsView;
_layout = layout;
Delegator.CarouselViewController = this;
CollectionView.AllowsSelection = false;
CollectionView.AllowsMultipleSelection = false;
}
protected override UICollectionViewDelegateFlowLayout CreateDelegator()
{
return new CarouselViewDelegator(ItemsViewLayout, this);
}
public override UICollectionViewCell GetCell(UICollectionView collectionView, NSIndexPath indexPath)
{
var cell = base.GetCell(collectionView, indexPath);
@ -60,6 +62,7 @@ namespace Xamarin.Forms.Platform.iOS
protected override void RegisterViewTypes()
{
CollectionView.RegisterClassForCell(typeof(CarouselTemplatedCell), CarouselTemplatedCell.ReuseId);
base.RegisterViewTypes();
}
internal void TearDown()

Просмотреть файл

@ -0,0 +1,28 @@
using UIKit;
namespace Xamarin.Forms.Platform.iOS
{
public class CarouselViewDelegator : ItemsViewDelegator<CarouselView, CarouselViewController>
{
public CarouselViewDelegator(ItemsViewLayout itemsViewLayout, CarouselViewController itemsViewController)
: base(itemsViewLayout, itemsViewController)
{
}
public override void DraggingStarted(UIScrollView scrollView)
{
ViewController?.DraggingStarted(scrollView);
PreviousHorizontalOffset = (float)scrollView.ContentOffset.X;
PreviousVerticalOffset = (float)scrollView.ContentOffset.Y;
}
public override void DraggingEnded(UIScrollView scrollView, bool willDecelerate)
{
PreviousHorizontalOffset = 0;
PreviousVerticalOffset = 0;
ViewController?.DraggingEnded(scrollView, willDecelerate);
}
}
}

Просмотреть файл

@ -2,20 +2,18 @@
namespace Xamarin.Forms.Platform.iOS
{
public class CarouselViewRenderer : ItemsViewRenderer
public class CarouselViewRenderer : ItemsViewRenderer<CarouselView, CarouselViewController>
{
CarouselView CarouselView => (CarouselView)Element;
CarouselViewController CarouselViewController => (CarouselViewController)ItemsViewController;
CarouselView CarouselView => Element;
public CarouselViewRenderer()
{
CollectionView.VerifyCollectionViewFlagEnabled(nameof(CarouselViewRenderer));
}
protected override ItemsViewController CreateController(ItemsView newElement, ItemsViewLayout layout)
protected override CarouselViewController CreateController(CarouselView newElement, ItemsViewLayout layout)
{
return new CarouselViewController(newElement as CarouselView, layout);
return new CarouselViewController(newElement, layout);
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs changedProperty)
@ -24,8 +22,8 @@ namespace Xamarin.Forms.Platform.iOS
if (changedProperty.IsOneOf(CarouselView.PeekAreaInsetsProperty, CarouselView.NumberOfSideItemsProperty))
{
(CarouselViewController.Layout as CarouselViewLayout).UpdateConstraints(Frame.Size);
CarouselViewController.Layout.InvalidateLayout();
(Controller.Layout as CarouselViewLayout).UpdateConstraints(Frame.Size);
Controller.Layout.InvalidateLayout();
}
else if (changedProperty.Is(CarouselView.IsSwipeEnabledProperty))
UpdateIsSwipeEnabled();
@ -38,16 +36,16 @@ namespace Xamarin.Forms.Platform.iOS
return new CarouselViewLayout(CarouselView.ItemsLayout, CarouselView.ItemSizingStrategy, CarouselView);
}
protected override void SetUpNewElement(ItemsView newElement)
protected override void SetUpNewElement(CarouselView newElement)
{
base.SetUpNewElement(newElement);
UpdateIsSwipeEnabled();
UpdateIsBounceEnabled();
}
protected override void TearDownOldElement(ItemsView oldElement)
protected override void TearDownOldElement(CarouselView oldElement)
{
CarouselViewController?.TearDown();
Controller?.TearDown();
base.TearDownOldElement(oldElement);
}
@ -56,7 +54,7 @@ namespace Xamarin.Forms.Platform.iOS
if (CarouselView == null)
return;
CarouselViewController.CollectionView.ScrollEnabled = CarouselView.IsSwipeEnabled;
Controller.CollectionView.ScrollEnabled = CarouselView.IsSwipeEnabled;
}
void UpdateIsBounceEnabled()
@ -64,7 +62,7 @@ namespace Xamarin.Forms.Platform.iOS
if (CarouselView == null)
return;
CarouselViewController.CollectionView.Bounces = CarouselView.IsBounceEnabled;
Controller.CollectionView.Bounces = CarouselView.IsBounceEnabled;
}
}
}

Просмотреть файл

@ -1,4 +1,4 @@
namespace Xamarin.Forms.Platform.iOS
{
public class CollectionViewRenderer : GroupableItemsViewRenderer { }
public class CollectionViewRenderer : GroupableItemsViewRenderer<GroupableItemsView, GroupableItemsViewController<GroupableItemsView>> { }
}

Просмотреть файл

@ -5,28 +5,32 @@ using UIKit;
namespace Xamarin.Forms.Platform.iOS
{
public class GroupableItemsViewController : SelectableItemsViewController
public class GroupableItemsViewController<TItemsView> : SelectableItemsViewController<TItemsView>
where TItemsView : GroupableItemsView
{
GroupableItemsView GroupableItemsView => (GroupableItemsView)ItemsView;
// Keep a cached value for the current state of grouping around so we can avoid hitting the
// BindableProperty all the time
bool _isGrouped;
Action _scrollAnimationEndedCallback;
public GroupableItemsViewController(GroupableItemsView groupableItemsView, ItemsViewLayout layout)
public GroupableItemsViewController(TItemsView groupableItemsView, ItemsViewLayout layout)
: base(groupableItemsView, layout)
{
_isGrouped = GroupableItemsView.IsGrouped;
_isGrouped = ItemsView.IsGrouped;
}
protected override UICollectionViewDelegateFlowLayout CreateDelegator()
{
return new GroupableItemsViewDelegator<TItemsView, GroupableItemsViewController<TItemsView>>(ItemsViewLayout, this);
}
protected override IItemsViewSource CreateItemsViewSource()
{
// Use the BindableProperty here (instead of _isGroupingEnabled) because the cached value might not be set yet
if (GroupableItemsView.IsGrouped)
if (ItemsView.IsGrouped)
{
return ItemsSourceFactory.CreateGrouped(GroupableItemsView.ItemsSource, CollectionView);
return ItemsSourceFactory.CreateGrouped(ItemsView.ItemsSource, CollectionView);
}
return base.CreateItemsViewSource();
@ -34,7 +38,7 @@ namespace Xamarin.Forms.Platform.iOS
public override void UpdateItemsSource()
{
_isGrouped = GroupableItemsView.IsGrouped;
_isGrouped = ItemsView.IsGrouped;
base.UpdateItemsSource();
}
@ -91,8 +95,8 @@ namespace Xamarin.Forms.Platform.iOS
void UpdateTemplatedSupplementaryView(TemplatedCell cell, NSString elementKind, NSIndexPath indexPath)
{
DataTemplate template = elementKind == UICollectionElementKindSectionKey.Header
? GroupableItemsView.GroupHeaderTemplate
: GroupableItemsView.GroupFooterTemplate;
? ItemsView.GroupHeaderTemplate
: ItemsView.GroupFooterTemplate;
var bindingContext = ItemsSource.Group(indexPath);
@ -108,10 +112,10 @@ namespace Xamarin.Forms.Platform.iOS
{
if (elementKind == UICollectionElementKindSectionKey.Header)
{
return DetermineViewReuseId(GroupableItemsView.GroupHeaderTemplate);
return DetermineViewReuseId(ItemsView.GroupHeaderTemplate);
}
return DetermineViewReuseId(GroupableItemsView.GroupFooterTemplate);
return DetermineViewReuseId(ItemsView.GroupFooterTemplate);
}
string DetermineViewReuseId(DataTemplate template)

Просмотреть файл

@ -0,0 +1,31 @@
using System;
using CoreGraphics;
using UIKit;
namespace Xamarin.Forms.Platform.iOS
{
public class GroupableItemsViewDelegator<TItemsView, TViewController> : SelectableItemsViewDelegator<TItemsView, TViewController>
where TItemsView : GroupableItemsView
where TViewController : GroupableItemsViewController<TItemsView>
{
public GroupableItemsViewDelegator(ItemsViewLayout itemsViewLayout, TViewController itemsViewController)
: base(itemsViewLayout, itemsViewController)
{
}
public override CGSize GetReferenceSizeForHeader(UICollectionView collectionView, UICollectionViewLayout layout, nint section)
{
return ViewController.GetReferenceSizeForHeader(collectionView, layout, section);
}
public override CGSize GetReferenceSizeForFooter(UICollectionView collectionView, UICollectionViewLayout layout, nint section)
{
return ViewController.GetReferenceSizeForFooter(collectionView, layout, section);
}
public override void ScrollAnimationEnded(UIScrollView scrollView)
{
ViewController?.HandleScrollAnimationEnded();
}
}
}

Просмотреть файл

@ -2,14 +2,13 @@
namespace Xamarin.Forms.Platform.iOS
{
public class GroupableItemsViewRenderer : SelectableItemsViewRenderer
public class GroupableItemsViewRenderer<TItemsView, TViewController> : SelectableItemsViewRenderer<TItemsView, TViewController>
where TItemsView : GroupableItemsView
where TViewController : GroupableItemsViewController<TItemsView>
{
GroupableItemsView GroupableItemsView => (GroupableItemsView)Element;
GroupableItemsViewController GroupableItemsViewController => (GroupableItemsViewController)ItemsViewController;
protected override ItemsViewController CreateController(ItemsView itemsView, ItemsViewLayout layout)
protected override TViewController CreateController(TItemsView itemsView, ItemsViewLayout layout)
{
return new GroupableItemsViewController(itemsView as GroupableItemsView, layout);
return new GroupableItemsViewController<TItemsView>(itemsView, layout) as TViewController;
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs changedProperty)
@ -18,7 +17,7 @@ namespace Xamarin.Forms.Platform.iOS
if (changedProperty.Is(GroupableItemsView.IsGroupedProperty))
{
GroupableItemsViewController?.UpdateItemsSource();
Controller?.UpdateItemsSource();
}
}
@ -45,7 +44,7 @@ namespace Xamarin.Forms.Platform.iOS
{
if (args.IsAnimated)
{
GroupableItemsViewController.SetScrollAnimationEndedCallback(() => base.ScrollToRequested(sender, args));
Controller.SetScrollAnimationEndedCallback(() => base.ScrollToRequested(sender, args));
}
else
{
@ -58,8 +57,8 @@ namespace Xamarin.Forms.Platform.iOS
bool WillNeedScrollAdjustment(ScrollToRequestEventArgs args)
{
return GroupableItemsView.ItemSizingStrategy == ItemSizingStrategy.MeasureAllItems
&& GroupableItemsView.IsGrouped
return ItemsView.ItemSizingStrategy == ItemSizingStrategy.MeasureAllItems
&& ItemsView.IsGrouped
&& (args.ScrollToPosition == ScrollToPosition.End || args.ScrollToPosition == ScrollToPosition.MakeVisible);
}
}

Просмотреть файл

@ -9,10 +9,11 @@ using Xamarin.Forms.Internals;
namespace Xamarin.Forms.Platform.iOS
{
// TODO hartez 2018/06/01 14:21:24 Add a method for updating the layout
public abstract class ItemsViewController : UICollectionViewController
public abstract class ItemsViewController<TItemsView> : UICollectionViewController
where TItemsView : ItemsView
{
public IItemsViewSource ItemsSource { get; protected set; }
public ItemsView ItemsView { get; }
public TItemsView ItemsView { get; }
protected ItemsViewLayout ItemsViewLayout { get; set; }
bool _initialConstraintsSet;
bool _isEmpty;
@ -23,9 +24,9 @@ namespace Xamarin.Forms.Platform.iOS
UIView _emptyUIView;
VisualElement _emptyViewFormsElement;
protected UICollectionViewDelegator Delegator { get; set; }
protected UICollectionViewDelegateFlowLayout Delegator { get; set; }
public ItemsViewController(ItemsView itemsView, ItemsViewLayout layout) : base(layout)
public ItemsViewController(TItemsView itemsView, ItemsViewLayout layout) : base(layout)
{
ItemsView = itemsView;
ItemsSource = CreateItemsViewSource();
@ -38,8 +39,6 @@ namespace Xamarin.Forms.Platform.iOS
ItemsViewLayout = layout;
ItemsViewLayout.GetPrototype = GetPrototype;
// If we're updating from a previous layout, we should keep any settings for the SelectableItemsViewController around
var selectableItemsViewController = Delegator?.SelectableItemsViewController;
Delegator = CreateDelegator();
CollectionView.Delegate = Delegator;
@ -140,13 +139,18 @@ namespace Xamarin.Forms.Platform.iOS
if (!_initialConstraintsSet)
{
ItemsViewLayout.ConstrainTo(CollectionView.Bounds.Size);
UpdateEmptyView();
_initialConstraintsSet = true;
}
else
{
ResizeEmptyView();
}
}
protected virtual UICollectionViewDelegator CreateDelegator()
protected virtual UICollectionViewDelegateFlowLayout CreateDelegator()
{
return new UICollectionViewDelegator(ItemsViewLayout, this);
return new ItemsViewDelegator<TItemsView, ItemsViewController<TItemsView>>(ItemsViewLayout, this);
}
protected virtual IItemsViewSource CreateItemsViewSource()
@ -267,6 +271,15 @@ namespace Xamarin.Forms.Platform.iOS
UpdateEmptyViewVisibility(ItemsSource?.ItemCount == 0);
}
void ResizeEmptyView()
{
if (_emptyUIView != null)
_emptyUIView.Frame = CollectionView.Frame;
if (_emptyViewFormsElement != null)
_emptyViewFormsElement.Layout(CollectionView.Frame.ToRectangle());
}
protected void UpdateSubview(object view, DataTemplate viewTemplate, ref UIView uiView, ref VisualElement formsElement)
{
uiView?.RemoveFromSuperview();

Просмотреть файл

@ -0,0 +1,125 @@
using System;
using System.Linq;
using CoreGraphics;
using Foundation;
using UIKit;
namespace Xamarin.Forms.Platform.iOS
{
public class ItemsViewDelegator<TItemsView, TViewController> : UICollectionViewDelegateFlowLayout
where TItemsView : ItemsView
where TViewController : ItemsViewController<TItemsView>
{
public ItemsViewLayout ItemsViewLayout { get; }
public TViewController ViewController { get; }
protected float PreviousHorizontalOffset, PreviousVerticalOffset;
public ItemsViewDelegator(ItemsViewLayout itemsViewLayout, TViewController itemsViewController)
{
ItemsViewLayout = itemsViewLayout;
ViewController = itemsViewController;
}
public override void Scrolled(UIScrollView scrollView)
{
var indexPathsForVisibleItems = ViewController.CollectionView.IndexPathsForVisibleItems.OrderBy(x => x.Row).ToList();
if (indexPathsForVisibleItems.Count == 0)
return;
var contentInset = scrollView.ContentInset;
var contentOffsetX = scrollView.ContentOffset.X + contentInset.Left;
var contentOffsetY = scrollView.ContentOffset.Y + contentInset.Top;
var firstVisibleItemIndex = (int)indexPathsForVisibleItems.First().Item;
var collectionView = ViewController.CollectionView;
var centerPoint = new CGPoint(collectionView.Center.X + collectionView.ContentOffset.X, collectionView.Center.Y + collectionView.ContentOffset.Y);
var centerIndexPath = collectionView.IndexPathForItemAtPoint(centerPoint);
var centerItemIndex = centerIndexPath?.Row ?? firstVisibleItemIndex;
var lastVisibleItemIndex = (int)indexPathsForVisibleItems.Last().Item;
var itemsViewScrolledEventArgs = new ItemsViewScrolledEventArgs
{
HorizontalDelta = contentOffsetX - PreviousHorizontalOffset,
VerticalDelta = contentOffsetY - PreviousVerticalOffset,
HorizontalOffset = contentOffsetX,
VerticalOffset = contentOffsetY,
FirstVisibleItemIndex = firstVisibleItemIndex,
CenterItemIndex = centerItemIndex,
LastVisibleItemIndex = lastVisibleItemIndex
};
var itemsView = ViewController.ItemsView;
var source = ViewController.ItemsSource;
itemsView.SendScrolled(itemsViewScrolledEventArgs);
PreviousHorizontalOffset = (float)contentOffsetX;
PreviousVerticalOffset = (float)contentOffsetY;
switch (itemsView.RemainingItemsThreshold)
{
case -1:
return;
case 0:
if (lastVisibleItemIndex == source.ItemCount - 1)
itemsView.SendRemainingItemsThresholdReached();
break;
default:
if (source.ItemCount - 1 - lastVisibleItemIndex <= itemsView.RemainingItemsThreshold)
itemsView.SendRemainingItemsThresholdReached();
break;
}
}
public override UIEdgeInsets GetInsetForSection(UICollectionView collectionView, UICollectionViewLayout layout,
nint section)
{
if (ItemsViewLayout == null)
{
return default;
}
return ItemsViewLayout.GetInsetForSection(collectionView, layout, section);
}
public override nfloat GetMinimumInteritemSpacingForSection(UICollectionView collectionView,
UICollectionViewLayout layout, nint section)
{
if (ItemsViewLayout == null)
{
return default;
}
return ItemsViewLayout.GetMinimumInteritemSpacingForSection(collectionView, layout, section);
}
public override nfloat GetMinimumLineSpacingForSection(UICollectionView collectionView,
UICollectionViewLayout layout, nint section)
{
if (ItemsViewLayout == null)
{
return default;
}
return ItemsViewLayout.GetMinimumLineSpacingForSection(collectionView, layout, section);
}
public override void CellDisplayingEnded(UICollectionView collectionView, UICollectionViewCell cell, NSIndexPath indexPath)
{
if (ItemsViewLayout.ScrollDirection == UICollectionViewScrollDirection.Horizontal)
{
var actualWidth = collectionView.ContentSize.Width - collectionView.Bounds.Size.Width;
if (collectionView.ContentOffset.X >= actualWidth || collectionView.ContentOffset.X < 0)
return;
}
else
{
var actualHeight = collectionView.ContentSize.Height - collectionView.Bounds.Size.Height;
if (collectionView.ContentOffset.Y >= actualHeight || collectionView.ContentOffset.Y < 0)
return;
}
}
}
}

Просмотреть файл

@ -484,7 +484,7 @@ namespace Xamarin.Forms.Platform.iOS
if (ItemsUpdatingScrollMode == ItemsUpdatingScrollMode.KeepLastItemInView)
{
ForceScrollToLastItem(CollectionView);
ForceScrollToLastItem(CollectionView, _itemsLayout);
}
}
@ -551,7 +551,7 @@ namespace Xamarin.Forms.Platform.iOS
return false;
}
static void ForceScrollToLastItem(UICollectionView collectionView)
static void ForceScrollToLastItem(UICollectionView collectionView, ItemsLayout itemsLayout)
{
var sections = (int)collectionView.NumberOfSections();
@ -566,7 +566,12 @@ namespace Xamarin.Forms.Platform.iOS
if (itemCount > 0)
{
var lastIndexPath = NSIndexPath.FromItemSection(itemCount - 1, section);
collectionView.ScrollToItem(lastIndexPath, UICollectionViewScrollPosition.Bottom, true);
if (itemsLayout.Orientation == ItemsLayoutOrientation.Vertical)
collectionView.ScrollToItem(lastIndexPath, UICollectionViewScrollPosition.Bottom, true);
else
collectionView.ScrollToItem(lastIndexPath, UICollectionViewScrollPosition.Right, true);
return;
}
}

Просмотреть файл

@ -4,28 +4,32 @@ using UIKit;
namespace Xamarin.Forms.Platform.iOS
{
public abstract class ItemsViewRenderer : ViewRenderer<ItemsView, UIView>
public abstract class ItemsViewRenderer<TItemsView, TViewController> : ViewRenderer<TItemsView, UIView>
where TItemsView : ItemsView
where TViewController : ItemsViewController<TItemsView>
{
ItemsViewLayout _layout;
bool _disposed;
bool? _defaultHorizontalScrollVisibility;
bool? _defaultVerticalScrollVisibility;
protected TItemsView ItemsView => Element;
public ItemsViewRenderer()
{
CollectionView.VerifyCollectionViewFlagEnabled(nameof(ItemsViewRenderer));
CollectionView.VerifyCollectionViewFlagEnabled(nameof(ItemsViewRenderer<TItemsView, TViewController>));
}
public override UIViewController ViewController => ItemsViewController;
public override UIViewController ViewController => Controller;
protected ItemsViewController ItemsViewController { get; private set; }
protected TViewController Controller { get; private set; }
public override SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
{
return Control.GetSizeRequest(widthConstraint, heightConstraint, 0, 0);
}
protected override void OnElementChanged(ElementChangedEventArgs<ItemsView> e)
protected override void OnElementChanged(ElementChangedEventArgs<TItemsView> e)
{
TearDownOldElement(e.OldElement);
SetUpNewElement(e.NewElement);
@ -37,27 +41,32 @@ namespace Xamarin.Forms.Platform.iOS
{
base.OnElementPropertyChanged(sender, changedProperty);
if (changedProperty.Is(ItemsView.ItemsSourceProperty))
if (changedProperty.Is(Xamarin.Forms.ItemsView.ItemsSourceProperty))
{
ItemsViewController.UpdateItemsSource();
UpdateItemsSource();
}
else if (changedProperty.IsOneOf(ItemsView.EmptyViewProperty, ItemsView.EmptyViewTemplateProperty))
else if (changedProperty.Is(Xamarin.Forms.ItemsView.ItemTemplateProperty))
{
ItemsViewController.UpdateEmptyView();
UpdateLayout();
}
else if (changedProperty.Is(ItemsView.ItemSizingStrategyProperty))
else if (changedProperty.IsOneOf(Xamarin.Forms.ItemsView.EmptyViewProperty,
Xamarin.Forms.ItemsView.EmptyViewTemplateProperty))
{
Controller.UpdateEmptyView();
}
else if (changedProperty.Is(Xamarin.Forms.ItemsView.ItemSizingStrategyProperty))
{
UpdateItemSizingStrategy();
}
else if (changedProperty.Is(ItemsView.HorizontalScrollBarVisibilityProperty))
else if (changedProperty.Is(Xamarin.Forms.ItemsView.HorizontalScrollBarVisibilityProperty))
{
UpdateHorizontalScrollBarVisibility();
}
else if (changedProperty.Is(ItemsView.VerticalScrollBarVisibilityProperty))
else if (changedProperty.Is(Xamarin.Forms.ItemsView.VerticalScrollBarVisibilityProperty))
{
UpdateVerticalScrollBarVisibility();
}
else if (changedProperty.Is(ItemsView.ItemsUpdatingScrollModeProperty))
else if (changedProperty.Is(Xamarin.Forms.ItemsView.ItemsUpdatingScrollModeProperty))
{
UpdateItemsUpdatingScrollMode();
}
@ -65,7 +74,7 @@ namespace Xamarin.Forms.Platform.iOS
protected abstract ItemsViewLayout SelectLayout();
protected virtual void TearDownOldElement(ItemsView oldElement)
protected virtual void TearDownOldElement(TItemsView oldElement)
{
if (oldElement == null)
{
@ -76,7 +85,7 @@ namespace Xamarin.Forms.Platform.iOS
oldElement.ScrollToRequested -= ScrollToRequested;
}
protected virtual void SetUpNewElement(ItemsView newElement)
protected virtual void SetUpNewElement(TItemsView newElement)
{
if (newElement == null)
{
@ -84,7 +93,7 @@ namespace Xamarin.Forms.Platform.iOS
}
UpdateLayout();
ItemsViewController = CreateController(newElement, _layout);
Controller = CreateController(newElement, _layout);
if (Forms.IsiOS11OrNewer)
{
@ -92,12 +101,11 @@ namespace Xamarin.Forms.Platform.iOS
// CollectionView content when we're in landscape mode (to avoid the notch)
// The SetUseSafeArea Platform Specific is already taking care of this for us
// That said, at some point it's possible folks will want a PS for controlling this behavior
ItemsViewController.CollectionView.ContentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentBehavior.Never;
Controller.CollectionView.ContentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentBehavior.Never;
}
SetNativeControl(ItemsViewController.View);
ItemsViewController.CollectionView.BackgroundColor = UIColor.Clear;
ItemsViewController.UpdateEmptyView();
SetNativeControl(Controller.View);
Controller.CollectionView.BackgroundColor = UIColor.Clear;
UpdateHorizontalScrollBarVisibility();
UpdateVerticalScrollBarVisibility();
@ -109,9 +117,9 @@ namespace Xamarin.Forms.Platform.iOS
{
_layout = SelectLayout();
if (ItemsViewController != null)
if (Controller != null)
{
ItemsViewController.UpdateLayout(_layout);
Controller.UpdateLayout(_layout);
}
}
@ -122,10 +130,15 @@ namespace Xamarin.Forms.Platform.iOS
protected virtual void UpdateItemsUpdatingScrollMode()
{
_layout.ItemsUpdatingScrollMode = Element.ItemsUpdatingScrollMode;
_layout.ItemsUpdatingScrollMode = ItemsView.ItemsUpdatingScrollMode;
}
protected abstract ItemsViewController CreateController(ItemsView newElement, ItemsViewLayout layout);
protected virtual void UpdateItemsSource()
{
Controller.UpdateItemsSource();
}
protected abstract TViewController CreateController(TItemsView newElement, ItemsViewLayout layout);
NSIndexPath DetermineIndex(ScrollToRequestEventArgs args)
{
@ -139,24 +152,24 @@ namespace Xamarin.Forms.Platform.iOS
return NSIndexPath.Create(args.GroupIndex, args.Index);
}
return ItemsViewController.GetIndexForItem(args.Item);
return Controller.GetIndexForItem(args.Item);
}
void UpdateVerticalScrollBarVisibility()
{
if (_defaultVerticalScrollVisibility == null)
_defaultVerticalScrollVisibility = ItemsViewController.CollectionView.ShowsVerticalScrollIndicator;
_defaultVerticalScrollVisibility = Controller.CollectionView.ShowsVerticalScrollIndicator;
switch (Element.VerticalScrollBarVisibility)
{
case ScrollBarVisibility.Always:
ItemsViewController.CollectionView.ShowsVerticalScrollIndicator = true;
Controller.CollectionView.ShowsVerticalScrollIndicator = true;
break;
case ScrollBarVisibility.Never:
ItemsViewController.CollectionView.ShowsVerticalScrollIndicator = false;
Controller.CollectionView.ShowsVerticalScrollIndicator = false;
break;
case ScrollBarVisibility.Default:
ItemsViewController.CollectionView.ShowsVerticalScrollIndicator = _defaultVerticalScrollVisibility.Value;
Controller.CollectionView.ShowsVerticalScrollIndicator = _defaultVerticalScrollVisibility.Value;
break;
}
}
@ -164,18 +177,18 @@ namespace Xamarin.Forms.Platform.iOS
void UpdateHorizontalScrollBarVisibility()
{
if (_defaultHorizontalScrollVisibility == null)
_defaultHorizontalScrollVisibility = ItemsViewController.CollectionView.ShowsHorizontalScrollIndicator;
_defaultHorizontalScrollVisibility = Controller.CollectionView.ShowsHorizontalScrollIndicator;
switch (Element.HorizontalScrollBarVisibility)
{
case ScrollBarVisibility.Always:
ItemsViewController.CollectionView.ShowsHorizontalScrollIndicator = true;
Controller.CollectionView.ShowsHorizontalScrollIndicator = true;
break;
case ScrollBarVisibility.Never:
ItemsViewController.CollectionView.ShowsHorizontalScrollIndicator = false;
Controller.CollectionView.ShowsHorizontalScrollIndicator = false;
break;
case ScrollBarVisibility.Default:
ItemsViewController.CollectionView.ShowsHorizontalScrollIndicator = _defaultHorizontalScrollVisibility.Value;
Controller.CollectionView.ShowsHorizontalScrollIndicator = _defaultHorizontalScrollVisibility.Value;
break;
}
}
@ -190,7 +203,7 @@ namespace Xamarin.Forms.Platform.iOS
return;
}
ItemsViewController.CollectionView.ScrollToItem(indexPath,
Controller.CollectionView.ScrollToItem(indexPath,
args.ScrollToPosition.ToCollectionViewScrollPosition(_layout.ScrollDirection), args.IsAnimated);
}
}
@ -208,8 +221,8 @@ namespace Xamarin.Forms.Platform.iOS
{
TearDownOldElement(Element);
ItemsViewController?.Dispose();
ItemsViewController = null;
Controller?.Dispose();
Controller = null;
}
base.Dispose(disposing);
@ -222,7 +235,7 @@ namespace Xamarin.Forms.Platform.iOS
return false;
}
var collectionView = ItemsViewController.CollectionView;
var collectionView = Controller.CollectionView;
if (indexPath.Section >= collectionView.NumberOfSections())
{
return false;

Просмотреть файл

@ -5,15 +5,19 @@ using UIKit;
namespace Xamarin.Forms.Platform.iOS
{
public class SelectableItemsViewController : StructuredItemsViewController
public class SelectableItemsViewController<TItemsView> : StructuredItemsViewController<TItemsView>
where TItemsView : SelectableItemsView
{
SelectableItemsView SelectableItemsView => (SelectableItemsView)ItemsView;
public SelectableItemsViewController(SelectableItemsView selectableItemsView, ItemsViewLayout layout)
public SelectableItemsViewController(TItemsView selectableItemsView, ItemsViewLayout layout)
: base(selectableItemsView, layout)
{
}
protected override UICollectionViewDelegateFlowLayout CreateDelegator()
{
return new SelectableItemsViewDelegator<TItemsView, SelectableItemsViewController<TItemsView>>(ItemsViewLayout, this);
}
// _Only_ called if the user initiates the selection change; will not be called for programmatic selection
public override void ItemSelected(UICollectionView collectionView, NSIndexPath indexPath)
{
@ -30,7 +34,11 @@ namespace Xamarin.Forms.Platform.iOS
internal void SelectItem(object selectedItem)
{
var index = GetIndexForItem(selectedItem);
CollectionView.SelectItem(index, true, UICollectionViewScrollPosition.None);
if (index.Section > -1 && index.Item > -1)
{
CollectionView.SelectItem(index, true, UICollectionViewScrollPosition.None);
}
}
// Called by Forms to clear the native selection
@ -46,24 +54,24 @@ namespace Xamarin.Forms.Platform.iOS
void FormsSelectItem(NSIndexPath indexPath)
{
var mode = SelectableItemsView.SelectionMode;
var mode = ItemsView.SelectionMode;
switch (mode)
{
case SelectionMode.None:
break;
case SelectionMode.Single:
SelectableItemsView.SelectedItem = GetItemAtIndex(indexPath);
ItemsView.SelectedItem = GetItemAtIndex(indexPath);
break;
case SelectionMode.Multiple:
SelectableItemsView.SelectedItems.Add(GetItemAtIndex(indexPath));
ItemsView.SelectedItems.Add(GetItemAtIndex(indexPath));
break;
}
}
void FormsDeselectItem(NSIndexPath indexPath)
{
var mode = SelectableItemsView.SelectionMode;
var mode = ItemsView.SelectionMode;
switch (mode)
{
@ -72,26 +80,26 @@ namespace Xamarin.Forms.Platform.iOS
case SelectionMode.Single:
break;
case SelectionMode.Multiple:
SelectableItemsView.SelectedItems.Remove(GetItemAtIndex(indexPath));
ItemsView.SelectedItems.Remove(GetItemAtIndex(indexPath));
break;
}
}
internal void UpdateNativeSelection()
{
if (SelectableItemsView == null)
if (ItemsView == null)
{
return;
}
var mode = SelectableItemsView.SelectionMode;
var mode = ItemsView.SelectionMode;
switch (mode)
{
case SelectionMode.None:
return;
case SelectionMode.Single:
var selectedItem = SelectableItemsView.SelectedItem;
var selectedItem = ItemsView.SelectedItem;
if (selectedItem != null)
{
@ -112,7 +120,7 @@ namespace Xamarin.Forms.Platform.iOS
internal void UpdateSelectionMode()
{
var mode = SelectableItemsView.SelectionMode;
var mode = ItemsView.SelectionMode;
switch (mode)
{
@ -135,7 +143,7 @@ namespace Xamarin.Forms.Platform.iOS
void SynchronizeNativeSelectionWithSelectedItems()
{
var selectedItems = SelectableItemsView.SelectedItems;
var selectedItems = ItemsView.SelectedItems;
var selectedIndexPaths = CollectionView.GetIndexPathsForSelectedItems();
foreach (var path in selectedIndexPaths)

Просмотреть файл

@ -0,0 +1,25 @@
using Foundation;
using UIKit;
namespace Xamarin.Forms.Platform.iOS
{
public class SelectableItemsViewDelegator<TItemsView, TViewController> : ItemsViewDelegator<TItemsView, TViewController>
where TItemsView : SelectableItemsView
where TViewController : SelectableItemsViewController<TItemsView>
{
public SelectableItemsViewDelegator(ItemsViewLayout itemsViewLayout, TViewController itemsViewController)
: base(itemsViewLayout, itemsViewController)
{
}
public override void ItemSelected(UICollectionView collectionView, NSIndexPath indexPath)
{
ViewController?.ItemSelected(collectionView, indexPath);
}
public override void ItemDeselected(UICollectionView collectionView, NSIndexPath indexPath)
{
ViewController?.ItemDeselected(collectionView, indexPath);
}
}
}

Просмотреть файл

@ -3,14 +3,13 @@ using System.ComponentModel;
namespace Xamarin.Forms.Platform.iOS
{
public class SelectableItemsViewRenderer : StructuredItemsViewRenderer
public class SelectableItemsViewRenderer<TItemsView, TViewController> : StructuredItemsViewRenderer<TItemsView, TViewController>
where TItemsView : SelectableItemsView
where TViewController : SelectableItemsViewController<TItemsView>
{
SelectableItemsView SelectableItemsView => (SelectableItemsView)Element;
SelectableItemsViewController SelectableItemsViewController => (SelectableItemsViewController)ItemsViewController;
protected override ItemsViewController CreateController(ItemsView itemsView, ItemsViewLayout layout)
protected override TViewController CreateController(TItemsView itemsView, ItemsViewLayout layout)
{
return new SelectableItemsViewController(itemsView as SelectableItemsView, layout);
return new SelectableItemsViewController<TItemsView>(itemsView, layout) as TViewController;
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs changedProperty)
@ -19,21 +18,16 @@ namespace Xamarin.Forms.Platform.iOS
if (changedProperty.IsOneOf(SelectableItemsView.SelectedItemProperty, SelectableItemsView.SelectedItemsProperty))
{
SelectableItemsViewController.UpdateNativeSelection();
UpdateNativeSelection();
}
else if (changedProperty.Is(SelectableItemsView.SelectionModeProperty))
{
SelectableItemsViewController.UpdateSelectionMode();
UpdateSelectionMode();
}
}
protected override void SetUpNewElement(ItemsView newElement)
protected override void SetUpNewElement(TItemsView newElement)
{
if (newElement != null && !(newElement is SelectableItemsView))
{
throw new ArgumentException($"{nameof(newElement)} must be of type {typeof(SelectableItemsView).Name}");
}
base.SetUpNewElement(newElement);
if (newElement == null)
@ -41,8 +35,24 @@ namespace Xamarin.Forms.Platform.iOS
return;
}
SelectableItemsViewController.UpdateSelectionMode();
SelectableItemsViewController.UpdateNativeSelection();
UpdateSelectionMode();
UpdateNativeSelection();
}
protected virtual void UpdateNativeSelection()
{
Controller.UpdateNativeSelection();
}
protected virtual void UpdateSelectionMode()
{
Controller.UpdateSelectionMode();
}
protected override void UpdateItemsSource()
{
base.UpdateItemsSource();
UpdateNativeSelection();
}
}
}

Просмотреть файл

@ -3,19 +3,18 @@ using UIKit;
namespace Xamarin.Forms.Platform.iOS
{
public class StructuredItemsViewController : ItemsViewController
public class StructuredItemsViewController<TItemsView> : ItemsViewController<TItemsView>
where TItemsView : StructuredItemsView
{
bool _disposed;
StructuredItemsView StructuredItemsView => (StructuredItemsView)ItemsView;
UIView _headerUIView;
VisualElement _headerViewFormsElement;
UIView _footerUIView;
VisualElement _footerViewFormsElement;
public StructuredItemsViewController(StructuredItemsView structuredItemsView, ItemsViewLayout layout)
public StructuredItemsViewController(TItemsView structuredItemsView, ItemsViewLayout layout)
: base(structuredItemsView, layout)
{
}
@ -41,7 +40,7 @@ namespace Xamarin.Forms.Platform.iOS
base.Dispose(disposing);
}
protected override bool IsHorizontal => (StructuredItemsView?.ItemsLayout as ItemsLayout)?.Orientation == ItemsLayoutOrientation.Horizontal;
protected override bool IsHorizontal => (ItemsView?.ItemsLayout as ItemsLayout)?.Orientation == ItemsLayoutOrientation.Horizontal;
public override void ViewWillLayoutSubviews()
{
@ -66,14 +65,14 @@ namespace Xamarin.Forms.Platform.iOS
internal void UpdateFooterView()
{
UpdateSubview(StructuredItemsView?.Footer, StructuredItemsView?.FooterTemplate,
UpdateSubview(ItemsView?.Footer, ItemsView?.FooterTemplate,
ref _footerUIView, ref _footerViewFormsElement);
UpdateHeaderFooterPosition();
}
internal void UpdateHeaderView()
{
UpdateSubview(StructuredItemsView?.Header, StructuredItemsView?.HeaderTemplate,
UpdateSubview(ItemsView?.Header, ItemsView?.HeaderTemplate,
ref _headerUIView, ref _headerViewFormsElement);
UpdateHeaderFooterPosition();
}

Просмотреть файл

@ -2,14 +2,13 @@
namespace Xamarin.Forms.Platform.iOS
{
public class StructuredItemsViewRenderer : ItemsViewRenderer
public class StructuredItemsViewRenderer<TItemsView, TViewController> : ItemsViewRenderer<TItemsView, TViewController>
where TItemsView : StructuredItemsView
where TViewController : StructuredItemsViewController<TItemsView>
{
StructuredItemsView StructuredItemsView => (StructuredItemsView)Element;
StructuredItemsViewController StructuredItemsViewController => (StructuredItemsViewController)ItemsViewController;
protected override ItemsViewController CreateController(ItemsView itemsView, ItemsViewLayout layout)
protected override TViewController CreateController(TItemsView itemsView, ItemsViewLayout layout)
{
return new StructuredItemsViewController(itemsView as StructuredItemsView, layout);
return new StructuredItemsViewController<TItemsView>(itemsView, layout) as TViewController;
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs changedProperty)
@ -18,19 +17,19 @@ namespace Xamarin.Forms.Platform.iOS
if (changedProperty.IsOneOf(StructuredItemsView.HeaderProperty, StructuredItemsView.HeaderTemplateProperty))
{
StructuredItemsViewController.UpdateHeaderView();
UpdateHeaderView();
}
else if (changedProperty.IsOneOf(StructuredItemsView.FooterProperty, StructuredItemsView.FooterTemplateProperty))
{
StructuredItemsViewController.UpdateFooterView();
UpdateFooterView();
}
else if (changedProperty.Is(StructuredItemsView.ItemsLayoutProperty))
{
StructuredItemsViewController.UpdateLayout(SelectLayout());
UpdateLayout();
}
}
protected override void SetUpNewElement(ItemsView newElement)
protected override void SetUpNewElement(TItemsView newElement)
{
base.SetUpNewElement(newElement);
@ -39,14 +38,14 @@ namespace Xamarin.Forms.Platform.iOS
return;
}
StructuredItemsViewController.UpdateFooterView();
StructuredItemsViewController.UpdateHeaderView();
Controller.UpdateFooterView();
Controller.UpdateHeaderView();
}
protected override ItemsViewLayout SelectLayout()
{
var itemSizingStrategy = StructuredItemsView.ItemSizingStrategy;
var itemsLayout = StructuredItemsView.ItemsLayout;
var itemSizingStrategy = ItemsView.ItemSizingStrategy;
var itemsLayout = ItemsView.ItemsLayout;
if (itemsLayout is GridItemsLayout gridItemsLayout)
{
@ -62,10 +61,20 @@ namespace Xamarin.Forms.Platform.iOS
return new ListViewLayout(new LinearItemsLayout(ItemsLayoutOrientation.Vertical), itemSizingStrategy);
}
protected virtual void UpdateHeaderView()
{
Controller.UpdateHeaderView();
}
protected virtual void UpdateFooterView()
{
Controller.UpdateFooterView();
}
public override void LayoutSubviews()
{
base.LayoutSubviews();
StructuredItemsViewController.UpdateLayoutMeasurements();
Controller.UpdateLayoutMeasurements();
}
}
}

Просмотреть файл

@ -1,174 +0,0 @@
using System;
using System.Linq;
using CoreGraphics;
using Foundation;
using UIKit;
namespace Xamarin.Forms.Platform.iOS
{
public class UICollectionViewDelegator : UICollectionViewDelegateFlowLayout
{
float _previousHorizontalOffset, _previousVerticalOffset;
public ItemsViewLayout ItemsViewLayout { get; }
public ItemsViewController ItemsViewController { get; }
public SelectableItemsViewController SelectableItemsViewController => ItemsViewController as SelectableItemsViewController;
public GroupableItemsViewController GroupableItemsViewController => ItemsViewController as GroupableItemsViewController;
public UICollectionViewDelegator(ItemsViewLayout itemsViewLayout, ItemsViewController itemsViewController)
{
ItemsViewLayout = itemsViewLayout;
ItemsViewController = itemsViewController;
}
public CarouselViewController CarouselViewController { get; set; }
public override void DraggingStarted(UIScrollView scrollView)
{
CarouselViewController?.DraggingStarted(scrollView);
_previousHorizontalOffset = (float)scrollView.ContentOffset.X;
_previousVerticalOffset = (float)scrollView.ContentOffset.Y;
}
public override void DraggingEnded(UIScrollView scrollView, bool willDecelerate)
{
_previousHorizontalOffset = 0;
_previousVerticalOffset = 0;
CarouselViewController?.DraggingEnded(scrollView, willDecelerate);
}
public override void Scrolled(UIScrollView scrollView)
{
var indexPathsForVisibleItems = ItemsViewController.CollectionView.IndexPathsForVisibleItems.OrderBy(x => x.Row).ToList();
if (indexPathsForVisibleItems.Count == 0)
return;
var contentInset = scrollView.ContentInset;
var contentOffsetX = scrollView.ContentOffset.X + contentInset.Left;
var contentOffsetY = scrollView.ContentOffset.Y + contentInset.Top;
var firstVisibleItemIndex = (int)indexPathsForVisibleItems.First().Item;
var centerPoint = new CGPoint(ItemsViewController.CollectionView.Center.X + ItemsViewController.CollectionView.ContentOffset.X, ItemsViewController.CollectionView.Center.Y + ItemsViewController.CollectionView.ContentOffset.Y);
var centerIndexPath = ItemsViewController.CollectionView.IndexPathForItemAtPoint(centerPoint);
var centerItemIndex = centerIndexPath?.Row ?? firstVisibleItemIndex;
var lastVisibleItemIndex = (int)indexPathsForVisibleItems.Last().Item;
var itemsViewScrolledEventArgs = new ItemsViewScrolledEventArgs
{
HorizontalDelta = contentOffsetX - _previousHorizontalOffset,
VerticalDelta = contentOffsetY - _previousVerticalOffset,
HorizontalOffset = contentOffsetX,
VerticalOffset = contentOffsetY,
FirstVisibleItemIndex = firstVisibleItemIndex,
CenterItemIndex = centerItemIndex,
LastVisibleItemIndex = lastVisibleItemIndex
};
ItemsViewController.ItemsView.SendScrolled(itemsViewScrolledEventArgs);
_previousHorizontalOffset = (float)contentOffsetX;
_previousVerticalOffset = (float)contentOffsetY;
switch (ItemsViewController.ItemsView.RemainingItemsThreshold)
{
case -1:
return;
case 0:
if (lastVisibleItemIndex == ItemsViewController.ItemsSource.ItemCount - 1)
ItemsViewController.ItemsView.SendRemainingItemsThresholdReached();
break;
default:
if (ItemsViewController.ItemsSource.ItemCount - 1 - lastVisibleItemIndex <= ItemsViewController.ItemsView.RemainingItemsThreshold)
ItemsViewController.ItemsView.SendRemainingItemsThresholdReached();
break;
}
}
public override UIEdgeInsets GetInsetForSection(UICollectionView collectionView, UICollectionViewLayout layout,
nint section)
{
if (ItemsViewLayout == null)
{
return default(UIEdgeInsets);
}
return ItemsViewLayout.GetInsetForSection(collectionView, layout, section);
}
public override nfloat GetMinimumInteritemSpacingForSection(UICollectionView collectionView,
UICollectionViewLayout layout, nint section)
{
if (ItemsViewLayout == null)
{
return default(nfloat);
}
return ItemsViewLayout.GetMinimumInteritemSpacingForSection(collectionView, layout, section);
}
public override nfloat GetMinimumLineSpacingForSection(UICollectionView collectionView,
UICollectionViewLayout layout, nint section)
{
if (ItemsViewLayout == null)
{
return default(nfloat);
}
return ItemsViewLayout.GetMinimumLineSpacingForSection(collectionView, layout, section);
}
public override void ItemSelected(UICollectionView collectionView, NSIndexPath indexPath)
{
SelectableItemsViewController?.ItemSelected(collectionView, indexPath);
}
public override void ItemDeselected(UICollectionView collectionView, NSIndexPath indexPath)
{
SelectableItemsViewController?.ItemDeselected(collectionView, indexPath);
}
public override void CellDisplayingEnded(UICollectionView collectionView, UICollectionViewCell cell, NSIndexPath indexPath)
{
if (ItemsViewLayout.ScrollDirection == UICollectionViewScrollDirection.Horizontal)
{
var actualWidth = collectionView.ContentSize.Width - collectionView.Bounds.Size.Width;
if (collectionView.ContentOffset.X >= actualWidth || collectionView.ContentOffset.X < 0)
return;
}
else
{
var actualHeight = collectionView.ContentSize.Height - collectionView.Bounds.Size.Height;
if (collectionView.ContentOffset.Y >= actualHeight || collectionView.ContentOffset.Y < 0)
return;
}
}
public override CGSize GetReferenceSizeForHeader(UICollectionView collectionView, UICollectionViewLayout layout, nint section)
{
if (GroupableItemsViewController == null)
{
return CGSize.Empty;
}
return GroupableItemsViewController.GetReferenceSizeForHeader(collectionView, layout, section);
}
public override CGSize GetReferenceSizeForFooter(UICollectionView collectionView, UICollectionViewLayout layout, nint section)
{
if (GroupableItemsViewController == null)
{
return CGSize.Empty;
}
return GroupableItemsViewController.GetReferenceSizeForFooter(collectionView, layout, section);
}
public override void ScrollAnimationEnded(UIScrollView scrollView)
{
GroupableItemsViewController?.HandleScrollAnimationEnded();
}
}
}

Просмотреть файл

@ -106,10 +106,12 @@
<Compile Include="$(MSBuildThisFileDirectory)Properties\AssemblyInfo.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Extensions\CellExtensions.cs" />
<Compile Include="CADisplayLinkTicker.cs" />
<Compile Include="CollectionView\CarouselViewDelegator.cs" />
<Compile Include="CollectionView\CarouselViewRenderer.cs" />
<Compile Include="CollectionView\CollectionViewRenderer.cs" />
<Compile Include="CollectionView\EmptySource.cs" />
<Compile Include="CollectionView\GroupableItemsViewController.cs" />
<Compile Include="CollectionView\GroupableItemsViewDelegator.cs" />
<Compile Include="CollectionView\GroupableItemsViewRenderer.cs" />
<Compile Include="CollectionView\HorizontalCell.cs" />
<Compile Include="CollectionView\HorizontalDefaultSupplementalView.cs" />
@ -124,9 +126,10 @@
<Compile Include="CollectionView\ObservableGroupedSource.cs" />
<Compile Include="CollectionView\ScrollToPositionExtensions.cs" />
<Compile Include="CollectionView\SelectableItemsViewController.cs" />
<Compile Include="CollectionView\SelectableItemsViewDelegator.cs" />
<Compile Include="CollectionView\SelectableItemsViewRenderer.cs" />
<Compile Include="CollectionView\TemplateHelpers.cs" />
<Compile Include="CollectionView\UICollectionViewDelegator.cs" />
<Compile Include="CollectionView\ItemsViewDelegator.cs" />
<Compile Include="CollectionView\VerticalCell.cs" />
<Compile Include="CollectionView\StructuredItemsViewController.cs" />
<Compile Include="CollectionView\StructuredItemsViewRenderer.cs" />

Просмотреть файл

@ -0,0 +1,16 @@
<?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="using:Xamarin.Forms.Xaml.UnitTests"
x:Class="Xamarin.Forms.Xaml.UnitTests.Gh7837">
<ContentPage.BindingContext>
<local:Gh7837VM />
</ContentPage.BindingContext>
<StackLayout>
<Label x:Name="label0" Text="{Binding .[42]}" />
<Label x:Name="label1" Text="{Binding .[foo]}" />
<Label x:Name="label2" Text="{Binding .[42]}" x:DataType="local:Gh7837VM" />
<Label x:Name="label3" Text="{Binding .[foo]}" x:DataType="local:Gh7837VM" />
</StackLayout>
</ContentPage>

Просмотреть файл

@ -0,0 +1,50 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using NUnit.Framework;
using Xamarin.Forms;
using Xamarin.Forms.Core.UnitTests;
namespace Xamarin.Forms.Xaml.UnitTests
{
public class Gh7837VMBase //using a base class to test #2131
{
public string this[int index] => "";
public string this[string index] => "";
}
public class Gh7837VM : Gh7837VMBase
{
public new string this[int index] => index == 42 ? "forty-two" : "dull number";
public new string this[string index] => index.ToUpper();
}
public partial class Gh7837 : ContentPage
{
public Gh7837() => InitializeComponent();
public Gh7837(bool useCompiledXaml)
{
//this stub will be replaced at compile time
}
[TestFixture]
class Tests
{
[SetUp] public void Setup() => Device.PlatformServices = new MockPlatformServices();
[TearDown] public void TearDown() => Device.PlatformServices = null;
[Test]
public void BindingWithMultipleIndexers([Values(false, true)]bool useCompiledXaml)
{
if (useCompiledXaml)
MockCompiler.Compile(typeof(Gh7837));
var layout = new Gh7837(useCompiledXaml);
Assert.That(layout.label0.Text, Is.EqualTo("forty-two"));
Assert.That(layout.label1.Text, Is.EqualTo("FOO"));
Assert.That(layout.label2.Text, Is.EqualTo("forty-two"));
Assert.That(layout.label3.Text, Is.EqualTo("FOO"));
}
}
}
}

Просмотреть файл

@ -35,8 +35,7 @@ namespace Xamarin.Forms.Xaml.UnitTests
BuildEngine = new MSBuild.UnitTests.DummyBuildEngine()
};
IList<Exception> exceptions;
if (xamlc.Execute(out exceptions) || exceptions == null || !exceptions.Any()) {
if (xamlc.Execute(out IList<Exception> exceptions) || exceptions == null || !exceptions.Any()) {
methdoDefinition = xamlc.InitCompForType;
return;
}

Просмотреть файл

@ -62,7 +62,7 @@ jobs:
displayName: Build Windows Phase
vmImage: $(winVmImage)
targetFolder: Xamarin.Forms.ControlGallery.Android/legacyRenderers/
msbuildExtraArguments: '/nowarn:VSX1000 /p:CreateAllAndroidTargets=true /bl:$(Build.ArtifactStagingDirectory)\win.binlog'
msbuildExtraArguments: '/nowarn:VSX1000 /p:CreateAllAndroidTargets=true'
buildConfiguration: $(DefaultBuildConfiguration)
buildPlatform: $(DefaultBuildPlatform)
provisionatorPath : 'build/provisioning/provisioning.csx'

Просмотреть файл

@ -51,9 +51,9 @@ string monoMajorVersion = "5.18.1";
string monoPatchVersion = "28";
string monoVersion = $"{monoMajorVersion}.{monoPatchVersion}";
string monoSDK_windows = $"https://download.mono-project.com/archive/{monoMajorVersion}/windows-installer/mono-{monoVersion}-x64-0.msi";
string androidSDK_windows = "https://aka.ms/xamarin-android-commercial-d15-9-windows";
string iOSSDK_windows = "https://download.visualstudio.microsoft.com/download/pr/71f33151-5db4-49cc-ac70-ba835a9f81e2/d256c6c50cd80ec0207783c5c7a4bc2f/xamarin.visualstudio.apple.sdk.4.12.3.83.vsix";
string monoSDK_windows = "";//$"https://download.mono-project.com/archive/{monoMajorVersion}/windows-installer/mono-{monoVersion}-x64-0.msi";
string androidSDK_windows = "";//"https://aka.ms/xamarin-android-commercial-d15-9-windows";
string iOSSDK_windows = "";//"https://download.visualstudio.microsoft.com/download/pr/71f33151-5db4-49cc-ac70-ba835a9f81e2/d256c6c50cd80ec0207783c5c7a4bc2f/xamarin.visualstudio.apple.sdk.4.12.3.83.vsix";
string macSDK_windows = "";
monoMajorVersion = "6.4.0";
@ -67,7 +67,7 @@ string macSDK_macos = $"https://bosstoragemirror.blob.core.windows.net/wrench/je
string androidSDK = IsRunningOnWindows() ? androidSDK_windows : androidSDK_macos;
string monoSDK = IsRunningOnWindows() ? monoSDK_windows : monoSDK_macos;
string iosSDK = IsRunningOnWindows() ? "" : iOSSDK_macos;
string iosSDK = IsRunningOnWindows() ? iOSSDK_windows : iOSSDK_macos;
string macSDK = IsRunningOnWindows() ? "" : macSDK_macos;
string[] androidSdkManagerInstalls = new string[0]; //new [] { "platforms;android-29"};
@ -77,6 +77,7 @@ string[] androidSdkManagerInstalls = new string[0]; //new [] { "platforms;androi
//////////////////////////////////////////////////////////////////////
Task("Clean")
.Description("Deletes all the obj/bin directories")
.Does(() =>
{
CleanDirectories("./**/obj", (fsi)=> !fsi.Path.FullPath.Contains("XFCorePostProcessor") && !fsi.Path.FullPath.StartsWith("tools"));
@ -84,6 +85,7 @@ Task("Clean")
});
Task("provision-macsdk")
.Description("Install Xamarin.Mac SDK")
.Does(async () =>
{
if(!IsRunningOnWindows() && !String.IsNullOrWhiteSpace(macSDK))
@ -93,16 +95,15 @@ Task("provision-macsdk")
});
Task("provision-iossdk")
.Description("Install Xamarin.iOS SDK")
.Does(async () =>
{
if(!IsRunningOnWindows())
{
if(!String.IsNullOrWhiteSpace(iosSDK))
await Boots(iosSDK);
}
if(!String.IsNullOrWhiteSpace(iosSDK))
await Boots(iosSDK);
});
Task("provision-androidsdk")
.Description("Install Xamarin.Android SDK")
.Does(async () =>
{
Information ("ANDROID_HOME: {0}", ANDROID_HOME);
@ -123,6 +124,7 @@ Task("provision-androidsdk")
});
Task("provision-monosdk")
.Description("Install Mono SDK")
.Does(async () =>
{
if(IsRunningOnWindows())
@ -155,17 +157,20 @@ Task("provision-monosdk")
});
Task("provision")
.Description("Install SDKs required to build project")
.IsDependentOn("provision-macsdk")
.IsDependentOn("provision-iossdk")
.IsDependentOn("provision-monosdk")
.IsDependentOn("provision-androidsdk");
Task("NuGetPack")
.Description("Build and Create Nugets")
.IsDependentOn("Build")
.IsDependentOn("_NuGetPack");
Task("_NuGetPack")
.Description("Create Nugets without building anything")
.Does(() =>
{
var nugetVersionFile =
@ -192,6 +197,7 @@ Task("_NuGetPack")
Task("Restore")
.Description("Restore target on Xamarin.Forms.sln")
.Does(() =>
{
try{
@ -204,20 +210,9 @@ Task("Restore")
}
});
Task("BuildHack")
.IsDependentOn("Restore")
.Does(() =>
{
if(!IsRunningOnWindows())
{
MSBuild("./Xamarin.Forms.Build.Tasks/Xamarin.Forms.Build.Tasks.csproj", GetMSBuildSettings().WithRestore());
}
});
Task("Build")
.Description("Builds all necessary projects to create Nuget Packages")
.IsDependentOn("Restore")
.IsDependentOn("BuildHack")
.IsDependentOn("Android81")
.Does(() =>
{
@ -232,7 +227,7 @@ Task("Build")
});
Task("Android81")
.IsDependentOn("BuildHack")
.Description("Builds Monodroid81 targets")
.Does(() =>
{
string[] androidProjects =
@ -252,7 +247,7 @@ Task("Android81")
});
Task("VSMAC")
.IsDependentOn("BuildHack")
.Description("Builds projects necessary so solution compiles on VSMAC")
.Does(() =>
{
StartProcess("open", new ProcessSettings{ Arguments = "Xamarin.Forms.sln" });
@ -274,7 +269,7 @@ Task("DeployiOS")
});
*/
Task("DeployAndroid")
.IsDependentOn("BuildHack")
.Description("Builds and deploy Android Control Gallery")
.Does(() =>
{
MSBuild("./Xamarin.Forms.Build.Tasks/Xamarin.Forms.Build.Tasks.csproj", GetMSBuildSettings().WithRestore());

Просмотреть файл

@ -73,7 +73,7 @@ jobs:
solution: ${{ parameters.slnPath }}
platform: '$(BuildPlatform)'
configuration: '$(BuildConfiguration)'
msbuildArguments: ${{ parameters.msbuildExtraArguments }} /p:JavaSdkDirectory="$(JAVA_HOME_8_X64)"
msbuildArguments: ${{ parameters.msbuildExtraArguments }} /p:JavaSdkDirectory="$(JAVA_HOME_8_X64)" /bl:$(Build.ArtifactStagingDirectory)\win-$(BuildConfiguration).binlog
- task: VSTest@2
displayName: 'Unit Tests'