This commit is contained in:
Shane Neuville 2020-06-10 15:37:45 -06:00
Родитель 0fb6dc55f8 71e13ec5f3
Коммит 227dd98ff6
49 изменённых файлов: 570 добавлений и 606 удалений

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

@ -19,11 +19,11 @@
<dependency id="Xamarin.Android.Support.v4" version="28.0.0.3"/>
</group>
<group targetFramework="MonoAndroid10.0">
<dependency id="Xamarin.AndroidX.Migration" version="1.0.0"/>
<dependency id="Xamarin.AndroidX.Migration" version="1.0.0.1"/>
<dependency id="Xamarin.Firebase.AppIndexing" version="71.1602.0"/>
<dependency id="Xamarin.Android.Support.v4" version="28.0.0.3"/>
<dependency id="Xamarin.AndroidX.Lifecycle.LiveData" version="2.1.0"/>
<dependency id="Xamarin.AndroidX.Legacy.Support.V4" version="1.0.0"/>
<dependency id="Xamarin.AndroidX.Lifecycle.LiveData" version="2.1.0.1"/>
<dependency id="Xamarin.AndroidX.Legacy.Support.V4" version="1.0.0.1"/>
</group>
</dependencies>
<references>

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

@ -18,11 +18,11 @@
<dependency id="Xamarin.Forms" version="$version$"/>
</group>
<group targetFramework="MonoAndroid10.0">
<dependency id="Xamarin.AndroidX.Migration" version="1.0.0"/>
<dependency id="Xamarin.AndroidX.Lifecycle.LiveData" version="2.1.0"/>
<dependency id="Xamarin.AndroidX.Legacy.Support.V4" version="1.0.0"/>
<dependency id="Xamarin.AndroidX.Legacy.Support.Core.UI" version="1.0.0"/>
<dependency id="Xamarin.AndroidX.AppCompat" version="1.1.0"/>
<dependency id="Xamarin.AndroidX.Migration" version="1.0.0.1"/>
<dependency id="Xamarin.AndroidX.Lifecycle.LiveData" version="2.1.0.1"/>
<dependency id="Xamarin.AndroidX.Legacy.Support.V4" version="1.0.0.1"/>
<dependency id="Xamarin.AndroidX.Legacy.Support.Core.UI" version="1.0.0.1"/>
<dependency id="Xamarin.AndroidX.AppCompat" version="1.1.0.1"/>
<dependency id="Xamarin.GooglePlayServices.Maps" version="71.1610.0"/>
<dependency id="Xamarin.Forms" version="$version$"/>
<dependency id="Xamarin.Android.Support.v4" version="28.0.0.3"/>

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

@ -25,8 +25,8 @@
<dependency id="Xamarin.Android.Support.v7.AppCompat" version="28.0.0.3"/>
</group>
<group targetFramework="MonoAndroid10.0">
<dependency id="Xamarin.AndroidX.Lifecycle.LiveData" version="2.1.0" />
<dependency id="Xamarin.Google.Android.Material" version="1.0.0" />
<dependency id="Xamarin.AndroidX.Lifecycle.LiveData" version="2.1.0.1" />
<dependency id="Xamarin.Google.Android.Material" version="1.0.0.1" />
</group>
<group targetFramework="Xamarin.iOS10">
<dependency id="Xamarin.iOS.MaterialComponents" version="92.0.0"/>

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

@ -15,10 +15,10 @@
<copyright>© Microsoft Corporation. All rights reserved.</copyright>
<dependencies>
<group targetFramework="MonoAndroid10.0">
<dependency id="Xamarin.AndroidX.Lifecycle.LiveData" version="2.1.0" />
<dependency id="Xamarin.Google.Android.Material" version="1.0.0" />
<dependency id="Xamarin.AndroidX.Legacy.Support.V4" version="1.0.0" />
<dependency id="Xamarin.AndroidX.Browser" version="1.0.0" />
<dependency id="Xamarin.AndroidX.Lifecycle.LiveData" version="2.1.0.1" />
<dependency id="Xamarin.Google.Android.Material" version="1.0.0.1" />
<dependency id="Xamarin.AndroidX.Legacy.Support.V4" version="1.0.0.1" />
<dependency id="Xamarin.AndroidX.Browser" version="1.0.0.1" />
</group>
<group targetFramework="MonoAndroid90">
<dependency id="Xamarin.Android.Support.v4" version="28.0.0.3"/>

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

@ -119,8 +119,8 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Xamarin.AndroidX.MediaRouter" Version="1.1.0" />
<PackageReference Include="Xamarin.AndroidX.Lifecycle.LiveData" Version="2.1.0" />
<PackageReference Include="Xamarin.AndroidX.MediaRouter" Version="1.1.0.1" />
<PackageReference Include="Xamarin.AndroidX.Lifecycle.LiveData" Version="2.1.0.1" />
<PackageReference Include="Xamarin.Google.Android.Material" Version="1.1.0-rc3" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />

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

@ -1,12 +1,12 @@
<Project>
<ItemGroup Condition="'$(TargetFrameworkVersion)' == 'v10.0'">
<PackageReference Include="Xamarin.AndroidX.Migration">
<Version>1.0.0</Version>
<Version>1.0.0.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.AndroidX.Browser" Version="1.0.0" />
<PackageReference Include="Xamarin.AndroidX.Palette" Version="1.0.0" />
<PackageReference Include="Xamarin.AndroidX.Lifecycle.LiveData" Version="2.1.0" />
<PackageReference Include="Xamarin.Google.Android.Material" Version="1.0.0" />
<PackageReference Include="Xamarin.AndroidX.Legacy.Support.V4" Version="1.0.0" />
<PackageReference Include="Xamarin.AndroidX.Browser" Version="1.0.0.1" />
<PackageReference Include="Xamarin.AndroidX.Palette" Version="1.0.0.1" />
<PackageReference Include="Xamarin.AndroidX.Lifecycle.LiveData" Version="2.1.0.1" />
<PackageReference Include="Xamarin.Google.Android.Material" Version="1.0.0.1" />
<PackageReference Include="Xamarin.AndroidX.Legacy.Support.V4" Version="1.0.0.1" />
</ItemGroup>
</Project>

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

@ -1,12 +1,12 @@
<Project>
<ItemGroup Condition="'$(TargetFrameworkVersion)' == 'v10.0'">
<PackageReference Include="Xamarin.AndroidX.Migration">
<Version>1.0.0</Version>
<Version>1.0.0.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.AndroidX.Browser" Version="1.0.0" />
<PackageReference Include="Xamarin.AndroidX.Palette" Version="1.0.0" />
<PackageReference Include="Xamarin.AndroidX.Lifecycle.LiveData" Version="2.1.0" />
<PackageReference Include="Xamarin.Google.Android.Material" Version="1.0.0" />
<PackageReference Include="Xamarin.AndroidX.Legacy.Support.V4" Version="1.0.0" />
<PackageReference Include="Xamarin.AndroidX.Browser" Version="1.0.0.1" />
<PackageReference Include="Xamarin.AndroidX.Palette" Version="1.0.0.1" />
<PackageReference Include="Xamarin.AndroidX.Lifecycle.LiveData" Version="2.1.0.1" />
<PackageReference Include="Xamarin.Google.Android.Material" Version="1.0.0.1" />
<PackageReference Include="Xamarin.AndroidX.Legacy.Support.V4" Version="1.0.0.1" />
</ItemGroup>
</Project>

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

@ -26,10 +26,10 @@
</ProjectReference>
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'MonoAndroid10.0'">
<PackageReference Include="Xamarin.AndroidX.Lifecycle.LiveData" Version="2.1.0" />
<PackageReference Include="Xamarin.AndroidX.Legacy.Support.V4" Version="1.0.0" />
<PackageReference Include="Xamarin.Google.Android.Material" Version="1.0.0" />
<PackageReference Include="Xamarin.AndroidX.RecyclerView" Version="1.1.0" />
<PackageReference Include="Xamarin.AndroidX.Lifecycle.LiveData" Version="2.1.0.1" />
<PackageReference Include="Xamarin.AndroidX.Legacy.Support.V4" Version="1.0.0.1" />
<PackageReference Include="Xamarin.Google.Android.Material" Version="1.0.0.1" />
<PackageReference Include="Xamarin.AndroidX.RecyclerView" Version="1.1.0.1" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'MonoAndroid90'">
<PackageReference Include="Xamarin.Android.Support.v4" Version="28.0.0.3" />

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

@ -1,12 +1,12 @@
<Project>
<ItemGroup Condition="'$(TargetFrameworkVersion)' == 'v10.0'">
<PackageReference Include="Xamarin.AndroidX.Migration">
<Version>1.0.0</Version>
</PackageReference>
<PackageReference Include="Xamarin.AndroidX.Lifecycle.LiveData" Version="2.1.0" />
<PackageReference Include="Xamarin.AndroidX.Browser" Version="1.0.0" />
<PackageReference Include="Xamarin.Google.Android.Material" Version="1.0.0" />
<PackageReference Include="Xamarin.AndroidX.Legacy.Support.V4" Version="1.0.0" />
<PackageReference Include="Xamarin.AndroidX.Palette" Version="1.0.0" />
<PackageReference Include="Xamarin.AndroidX.Migration">
<Version>1.0.0.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.AndroidX.Lifecycle.LiveData" Version="2.1.0.1" />
<PackageReference Include="Xamarin.AndroidX.Browser" Version="1.0.0.1" />
<PackageReference Include="Xamarin.Google.Android.Material" Version="1.0.0.1" />
<PackageReference Include="Xamarin.AndroidX.Legacy.Support.V4" Version="1.0.0.1" />
<PackageReference Include="Xamarin.AndroidX.Palette" Version="1.0.0.1" />
</ItemGroup>
</Project>

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

@ -12,7 +12,6 @@ using Xamarin.Forms.Controls;
[assembly: UsesPermission(Android.Manifest.Permission.Internet)]
[assembly: UsesPermission(Android.Manifest.Permission.WriteExternalStorage)]
[assembly: Android.App.MetaData("com.google.android.maps.v2.API_KEY", Value = "AIzaSyAdstcJQswxEjzX5YjLaMcu2aRVEBJw39Y")]
[assembly: Xamarin.Forms.ResolutionGroupName(Xamarin.Forms.Controls.Issues.Effects.ResolutionGroupName)]
// Deliberately broken image source and handler so we can test handling of image loading errors

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

@ -1,6 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Android.App;
[assembly: Android.App.MetaData("com.google.android.maps.v2.API_KEY", Value = "")]

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

@ -109,7 +109,6 @@
<Compile Include="Tests\TestingPlatformService.cs" />
<Compile Include="Tests\PlatformTestSettings.cs" />
<Compile Include="PreApplicationClassActivity.cs" />
<Compile Include="Properties\MapsKey.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RegistrarValidationService.cs" />
<Compile Include="CustomRenderers.cs" />
@ -405,12 +404,9 @@
<SubType>Designer</SubType>
</AndroidResource>
</ItemGroup>
<ItemGroup Condition="Exists('Properties\MapsKey.cs')">
<Compile Include="Properties\MapsKey.cs" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="$(FromSource) == 'true' AND Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
<Target Name="BeforeBuild">
<CreateItem Include="Properties\MapsKey.cs.blank">
<Output TaskParameter="Include" ItemName="MapsKey" />
</CreateItem>
<Copy SourceFiles="@(MapsKey)" DestinationFiles="Properties\MapsKey.cs" Condition="!Exists('Properties\MapsKey.cs')" />
</Target>
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
</Project>

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

@ -22,7 +22,7 @@ namespace Xamarin.Forms.ControlGallery.Tizen
{
var app = new MainApplication();
FormsMaps.Init("HERE", "write-your-API-key-here");
Forms.SetFlags("CollectionView_Experimental", "Shell_Experimental", "MediaElement_Experimental", "IndicatorView_Experimental");
Forms.SetFlags("CollectionView_Experimental", "Shell_Experimental", "MediaElement_Experimental");
Forms.Init(app);
FormsMaterial.Init();
app.Run(args);

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

@ -27,9 +27,6 @@ namespace Xamarin.Forms.Controls.Issues
protected override void Init()
{
#if APP
Device.SetFlags(new List<string>(Device.Flags ?? new List<string>()) { "IndicatorView_Experimental" });
#endif
var layout = new StackLayout();
var instructions = new Label

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

@ -21,7 +21,6 @@ namespace Xamarin.Forms.Controls.Issues
public Issue8958()
{
#if APP
Device.SetFlags(new List<string>(Device.Flags ?? new List<string>()) { "IndicatorView_Experimental" });
InitializeComponent();
#endif
}

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

@ -30,7 +30,7 @@ namespace Xamarin.Forms.Controls.Issues
public Issue9827()
{
#if APP
Device.SetFlags(new List<string>(Device.Flags ?? new List<string>()) { ExperimentalFlags.IndicatorViewExperimental, ExperimentalFlags.CarouselViewExperimental });
Device.SetFlags(new List<string>(Device.Flags ?? new List<string>()) { ExperimentalFlags.CarouselViewExperimental });
InitializeComponent();
#endif
}

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

@ -66,7 +66,7 @@ namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries.CarouselVi
button.TextColor = Color.Black;
button.IsEnabled = false;
Device.SetFlags(new[] { ExperimentalFlags.CarouselViewExperimental, ExperimentalFlags.IndicatorViewExperimental });
Device.SetFlags(new[] { ExperimentalFlags.CarouselViewExperimental });
}
}
}

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

@ -1,6 +1,4 @@
using System;
namespace Xamarin.Forms.Controls.GalleryPages
namespace Xamarin.Forms.Controls.GalleryPages
{
public class IndicatorGalleries : ContentPage
{
@ -11,13 +9,6 @@ namespace Xamarin.Forms.Controls.GalleryPages
Title = "IndicatorView Galleries";
var button = new Button
{
Text = "Enable IndicatorView",
AutomationId = "EnableIndicator"
};
button.Clicked += ButtonClicked;
Content = new ScrollView
{
Content = new StackLayout
@ -25,7 +16,6 @@ namespace Xamarin.Forms.Controls.GalleryPages
Children =
{
descriptionLabel,
button,
GalleryBuilder.NavButton("IndicatorView Gallery", () =>
new IndicatorsSample(), Navigation),
GalleryBuilder.NavButton("Indicator MaxVisible Gallery", () =>
@ -34,16 +24,5 @@ namespace Xamarin.Forms.Controls.GalleryPages
}
};
}
void ButtonClicked(object sender, EventArgs e)
{
var button = sender as Button;
button.Text = "IndicatorView Enabled!";
button.TextColor = Color.Black;
button.IsEnabled = false;
Device.SetFlags(new[] { ExperimentalFlags.IndicatorViewExperimental });
}
}
}

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

@ -16,28 +16,31 @@ namespace Xamarin.Forms.Controls.GalleryPages.ShapesGalleries
};
button.Clicked += ButtonClicked;
Content = new StackLayout
Content = new ScrollView
{
Children =
{
button,
GalleryBuilder.NavButton("Path Gallery", () => new PathGallery(), Navigation),
GalleryBuilder.NavButton("Path Aspect Gallery", () => new PathAspectGallery(), Navigation),
GalleryBuilder.NavButton("Path LayoutOptions Gallery", () => new PathLayoutOptionsGallery(), Navigation),
GalleryBuilder.NavButton("Transform Playground", () => new TransformPlaygroundGallery(), Navigation),
GalleryBuilder.NavButton("Path Transform using string (TypeConverter) Gallery", () => new PathTransformStringGallery(), Navigation),
GalleryBuilder.NavButton("Clip Gallery", () => new ClipGallery(), Navigation),
GalleryBuilder.NavButton("Clip Views Gallery", () => new ClipViewsGallery(), Navigation),
GalleryBuilder.NavButton("Add/Remove Clip Gallery", () => new AddRemoveClipGallery(), Navigation),
GalleryBuilder.NavButton("Clip Performance Gallery", () => new ClipPerformanceGallery(), Navigation),
GalleryBuilder.NavButton("Ellipse Gallery", () => new EllipseGallery(), Navigation),
GalleryBuilder.NavButton("Line Gallery", () => new LineGallery(), Navigation),
GalleryBuilder.NavButton("Polygon Gallery", () => new PolygonGallery(), Navigation),
GalleryBuilder.NavButton("Polyline Gallery", () => new PolylineGallery(), Navigation),
GalleryBuilder.NavButton("Rectangle Gallery", () => new RectangleGallery(), Navigation),
GalleryBuilder.NavButton("LineCap Gallery", () => new LineCapGallery(), Navigation),
GalleryBuilder.NavButton("LineJoin Gallery", () => new LineJoinGallery(), Navigation),
GalleryBuilder.NavButton("AutoSize Shapes Gallery", () => new AutoSizeShapesGallery(), Navigation)
Content = new StackLayout
{
Children =
{
button,
GalleryBuilder.NavButton("Ellipse Gallery", () => new EllipseGallery(), Navigation),
GalleryBuilder.NavButton("Line Gallery", () => new LineGallery(), Navigation),
GalleryBuilder.NavButton("Polygon Gallery", () => new PolygonGallery(), Navigation),
GalleryBuilder.NavButton("Polyline Gallery", () => new PolylineGallery(), Navigation),
GalleryBuilder.NavButton("Rectangle Gallery", () => new RectangleGallery(), Navigation),
GalleryBuilder.NavButton("LineCap Gallery", () => new LineCapGallery(), Navigation),
GalleryBuilder.NavButton("LineJoin Gallery", () => new LineJoinGallery(), Navigation),
GalleryBuilder.NavButton("AutoSize Shapes Gallery", () => new AutoSizeShapesGallery(), Navigation),
GalleryBuilder.NavButton("Path Gallery", () => new PathGallery(), Navigation),
GalleryBuilder.NavButton("Path Aspect Gallery", () => new PathAspectGallery(), Navigation),
GalleryBuilder.NavButton("Path LayoutOptions Gallery", () => new PathLayoutOptionsGallery(), Navigation),
GalleryBuilder.NavButton("Transform Playground", () => new TransformPlaygroundGallery(), Navigation),
GalleryBuilder.NavButton("Path Transform using string (TypeConverter) Gallery", () => new PathTransformStringGallery(), Navigation),
GalleryBuilder.NavButton("Clip Gallery", () => new ClipGallery(), Navigation),
GalleryBuilder.NavButton("Clip Views Gallery", () => new ClipViewsGallery(), Navigation),
GalleryBuilder.NavButton("Add/Remove Clip Gallery", () => new AddRemoveClipGallery(), Navigation),
GalleryBuilder.NavButton("Clip Performance Gallery", () => new ClipPerformanceGallery(), Navigation)
}
}
};
}

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

@ -307,15 +307,15 @@ namespace Xamarin.Forms.Controls.XamStore
Content = new ScrollView { Content = grid };
grid.Children.Add(MakeButton("FlyoutBackdrop Color",
() =>
{
if (Shell.GetFlyoutBackdropColor(Shell.Current) == Color.Default)
Shell.SetFlyoutBackdropColor(Shell.Current, Color.Purple);
else
Shell.SetFlyoutBackdropColor(Shell.Current, Color.Default);
}),
0, 21);
//grid.Children.Add(MakeButton("FlyoutBackdrop Color",
// () =>
// {
// if (Shell.GetFlyoutBackdropColor(Shell.Current) == Color.Default)
// Shell.SetFlyoutBackdropColor(Shell.Current, Color.Purple);
// else
// Shell.SetFlyoutBackdropColor(Shell.Current, Color.Default);
// }),
// 0, 21);
grid.Children.Add(MakeButton("Hide Nav Shadow",
() => Shell.SetNavBarHasShadow(this, false)),

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

@ -33,16 +33,8 @@ namespace Xamarin.Forms.Core.UnitTests
}
[Test]
public void TestChildOneWayOverridesMultiTwoWay()
public void TestChildOneWayOnMultiTwoWay()
{
// This tests a weird edge case where the MultiBinding is TwoWay but
// one of the child bindings is OneWay. This results in a situation where
// you actually can't change the target value to be inconsistent with the
// the source value for the OneWay because ConvertBack causes Convert
// to get re-evaluated (and this effectively negates the change to the
// target). This ensures that the target and source never go out of sync,
// as the overall binding is still TwoWay.
var group = new GroupViewModel();
var stack = new StackLayout
{
@ -71,8 +63,7 @@ namespace Xamarin.Forms.Core.UnitTests
Assert.AreEqual(oldName, label.Text);
Assert.AreEqual(oldName, group.Person1.FullName);
label.Text = $"{oldFirstName.ToUpper()} {oldMiddleName} {oldLastName.ToUpper()}";
Assert.AreEqual($"{oldFirstName} {oldMiddleName} {oldLastName.ToUpper()}", label.Text);
label.SetValueCore(Label.TextProperty, $"{oldFirstName.ToUpper()} {oldMiddleName} {oldLastName.ToUpper()}", Internals.SetValueFlags.None);
Assert.AreEqual($"{oldFirstName} {oldMiddleName} {oldLastName.ToUpper()}", group.Person1.FullName);
}
@ -100,7 +91,7 @@ namespace Xamarin.Forms.Core.UnitTests
Assert.AreEqual("Courier New 12 Italic", entry1.Text);
// Our unit test's ConvertBack should throw an exception below because the desired
// return types aren't all strings
Assert.Throws<Exception>(new TestDelegate(() => entry1.Text = "Arial 12 Italic"));
Assert.Throws<Exception>(() => entry1.SetValueCore(Entry.TextProperty, "Arial 12 Italic", Internals.SetValueFlags.None));
// FindAncestor and FindAncestorBindingContext
// are already tested in TestNestedMultiBindings
@ -137,14 +128,10 @@ namespace Xamarin.Forms.Core.UnitTests
var checkBox = new CheckBox();
checkBox.SetBinding(
CheckBox.IsCheckedProperty,
new MultiBinding
{
Bindings = new Collection<BindingBase>
{
new MultiBinding
{
Bindings = new Collection<BindingBase>
{
new MultiBinding {
Bindings = {
new MultiBinding {
Bindings = {
new Binding(nameof(PersonViewModel.IsOver16)),
new Binding(nameof(PersonViewModel.HasPassedTest)),
new Binding(nameof(PersonViewModel.IsSuspended), converter: new Inverter()),
@ -162,7 +149,8 @@ namespace Xamarin.Forms.Core.UnitTests
$"{nameof(Element.BindingContext)}.{nameof(GroupViewModel.PardonAllSuspensions)}",
source: new RelativeBindingSource(RelativeBindingSourceMode.FindAncestor, typeof(StackLayout))),
},
Converter = new AnyTrueMultiConverter()
Converter = new AnyTrueMultiConverter(),
FallbackValue = false,
});
// ^^
@ -235,22 +223,22 @@ namespace Xamarin.Forms.Core.UnitTests
var label2 = GenerateNameLabel(nameof(group.Person2), BindingMode.TwoWay);
stack.Children.Add(label2);
label2.Text = $"DoNothing {oldMiddleName} {oldLastName.ToUpper()}";
label2.SetValueCore(Label.TextProperty, $"DoNothing {oldMiddleName} {oldLastName.ToUpper()}", Internals.SetValueFlags.None);
Assert.AreEqual($"{oldFirstName} {oldMiddleName} {oldLastName.ToUpper()}", group.Person2.FullName);
Assert.AreEqual(group.Person2.FullName, label2.Text);
Assert.AreEqual($"DoNothing {oldMiddleName} {oldLastName.ToUpper()}", label2.Text);
label2.Text = oldName;
Assert.AreEqual(oldName, group.Person2.FullName);
Assert.AreEqual(oldName, label2.Text);
// Any UnsetValue prevents any changes to source but target accepts value
label2.Text = $"{oldFirstName.ToUpper()} UnsetValue {oldLastName}";
Assert.AreEqual(oldName, group.Person2.FullName);
label2.SetValueCore(Label.TextProperty, $"{oldFirstName.ToUpper()} UnsetValue {oldLastName}");
Assert.AreEqual($"{oldFirstName.ToUpper()} {oldMiddleName} {oldLastName}", group.Person2.FullName);
Assert.AreEqual($"{oldFirstName.ToUpper()} UnsetValue {oldLastName}", label2.Text);
label2.Text = oldName;
Assert.AreEqual(oldName, group.Person2.FullName);
Assert.AreEqual(oldName, label2.Text);
label2.Text = "null";
label2.SetValueCore(Label.TextProperty, "null");
// Returning null prevents changes to source but target accepts value
Assert.AreEqual(oldName, group.Person2.FullName);
Assert.AreEqual("null", label2.Text);
@ -259,67 +247,65 @@ namespace Xamarin.Forms.Core.UnitTests
label2.Text = oldName;
Assert.AreEqual(oldName, group.Person2.FullName);
Assert.AreEqual(oldName, label2.Text);
label2.Text = $"Duck Duck";
label2.SetValueCore(Label.TextProperty, $"Duck Duck", Internals.SetValueFlags.None);
Assert.AreEqual($"Duck Duck {oldLastName}", group.Person2.FullName);
// Target can't go out of sync with source
Assert.AreEqual($"Duck Duck {oldLastName}", label2.Text);
Assert.AreEqual($"Duck Duck", label2.Text);
// Too many members are no problem either
label2.Text = oldName;
Assert.AreEqual(oldName, group.Person2.FullName);
label2.Text = oldName + " Extra";
label2.SetValueCore(Label.TextProperty, oldName + " Extra", Internals.SetValueFlags.None);
Assert.AreEqual(oldName, group.Person2.FullName);
// Target still won't go out of sync with source
Assert.AreEqual(oldName, label2.Text);
Assert.AreEqual(oldName + " Extra", label2.Text);
}
[Test]
public void TestEfficiency()
{
var group = new GroupViewModel();
var stack = new StackLayout
{
BindingContext = group.Person1
};
//[Test]
//public void TestEfficiency()
//{
// var group = new GroupViewModel();
// var stack = new StackLayout
// {
// BindingContext = group.Person1
// };
string oldName = group.Person1.FullName;
// string oldName = group.Person1.FullName;
var converter = new StringConcatenationConverter();
// var converter = new StringConcatenationConverter();
var label = new Label();
label.SetBinding(Label.TextProperty, new MultiBinding
{
Bindings = new Collection<BindingBase>
{
new Binding(nameof(PersonViewModel.FirstName)),
new Binding(nameof(PersonViewModel.MiddleName)),
new Binding(nameof(PersonViewModel.LastName)),
},
Converter = converter,
Mode = BindingMode.TwoWay,
});
// var label = new Label();
// label.SetBinding(Label.TextProperty, new MultiBinding
// {
// Bindings = new Collection<BindingBase>
// {
// new Binding(nameof(PersonViewModel.FirstName)),
// new Binding(nameof(PersonViewModel.MiddleName)),
// new Binding(nameof(PersonViewModel.LastName)),
// },
// Converter = converter,
// Mode = BindingMode.TwoWay,
// });
// Initial binding should result in 1 Convert, no ConvertBack's
Assert.AreEqual(1, converter.Converts);
Assert.AreEqual(0, converter.ConvertBacks);
// // Initial binding should result in 1 Convert, no ConvertBack's
// Assert.AreEqual(1, converter.Converts);
// Assert.AreEqual(0, converter.ConvertBacks);
// Parenting results in bctx change; should be 1 additional Convert, no ConvertBack's
stack.Children.Add(label);
Assert.AreEqual(group.Person1.FullName, label.Text);
Assert.AreEqual(2, converter.Converts);
Assert.AreEqual(0, converter.ConvertBacks);
// // Parenting results in bctx change; should be 1 additional Convert, no ConvertBack's
// stack.Children.Add(label);
// Assert.AreEqual(group.Person1.FullName, label.Text);
// Assert.AreEqual(2, converter.Converts);
// Assert.AreEqual(0, converter.ConvertBacks);
// Source change results in 1 additional Convert, no ConvertBack's
group.Person1.FirstName = group.Person1.FullName.ToUpper();
Assert.AreEqual(3, converter.Converts);
Assert.AreEqual(0, converter.ConvertBacks);
// // Source change results in 1 additional Convert, no ConvertBack's
// group.Person1.FirstName = group.Person1.FullName.ToUpper();
// Assert.AreEqual(3, converter.Converts);
// Assert.AreEqual(0, converter.ConvertBacks);
// Target change results in 1 ConvertBack, one additional Convert
label.Text = oldName;
Assert.AreEqual(oldName, group.Person1.FullName);
Assert.AreEqual(4, converter.Converts);
Assert.AreEqual(1, converter.ConvertBacks);
}
// // Target change results in 1 ConvertBack, one additional Convert
// label.Text = oldName;
// Assert.AreEqual(oldName, group.Person1.FullName);
// Assert.AreEqual(4, converter.Converts);
// Assert.AreEqual(1, converter.ConvertBacks);
//}
[Test]
public void TestBindingModes()
@ -335,7 +321,6 @@ namespace Xamarin.Forms.Core.UnitTests
stack.Children.Add(label1W);
Assert.AreEqual(group.Person1.FullName, label1W.Text);
label1W.SetValueCore(Label.TextProperty, "don't change source", Internals.SetValueFlags.None);
Assert.AreEqual("don't change source", label1W.Text);
Assert.AreEqual(oldName, group.Person1.FullName);
var label2W = GenerateNameLabel(nameof(group.Person2), BindingMode.TwoWay);
@ -347,10 +332,8 @@ namespace Xamarin.Forms.Core.UnitTests
oldName = group.Person3.FullName;
var label1WTS = GenerateNameLabel(nameof(group.Person3), BindingMode.OneWayToSource);
stack.Children.Add(label1WTS);
// Initial value is target fallback
Assert.AreEqual(c_Fallback, label1WTS.Text);
Assert.AreEqual(c_Fallback, group.Person3.FullName);
label1WTS.Text = oldName;
Assert.AreEqual(Label.TextProperty.DefaultValue, label1WTS.Text);
label1WTS.SetValueCore(Label.TextProperty, oldName, Internals.SetValueFlags.None);
Assert.AreEqual(oldName, label1WTS.Text);
Assert.AreEqual(oldName, group.Person3.FullName);
@ -369,6 +352,24 @@ namespace Xamarin.Forms.Core.UnitTests
Assert.AreEqual(group.Person1.FullName, label1T.Text);
}
[Test]
public void TestStringFormat()
{
var property = BindableProperty.Create("foo", typeof(string), typeof(MockBindable), null);
var bindable = new MockBindable();
var multibinding = new MultiBinding {
Bindings = {
new Binding ("foo"),
new Binding ("bar"),
new Binding ("baz"),
},
StringFormat = "{0} - {1} - {2}"
};
Assert.DoesNotThrow(()=>bindable.SetBinding(property, multibinding));
Assert.DoesNotThrow(()=>bindable.BindingContext = new { foo = "FOO", bar = 42, baz = "BAZ" });
Assert.That(bindable.GetValue(property), Is.EqualTo("FOO - 42 - BAZ"));
}
private Label GenerateNameLabel(string person, BindingMode mode)
{
var label = new Label();
@ -479,7 +480,7 @@ namespace Xamarin.Forms.Core.UnitTests
if (values is null)
return null;
string concatenator = parameter as string ?? " ";
string separator = parameter as string ?? " ";
StringBuilder sb = new StringBuilder();
int i = 0;
@ -495,8 +496,8 @@ namespace Xamarin.Forms.Core.UnitTests
if (value as string == "null")
return null;
if (i != 0 && concatenator != null)
sb.Append(concatenator);
if (i != 0 && separator != null)
sb.Append(separator);
sb.Append(value?.ToString());
i++;
}
@ -511,13 +512,13 @@ namespace Xamarin.Forms.Core.UnitTests
if (s == "null" || string.IsNullOrEmpty(s))
return null;
string concatenator = parameter as string ?? " ";
string separator = parameter as string ?? " ";
if (!targetTypes.All(t => t == typeof(string)))
if (!targetTypes.All(t=>t==typeof(object)) && !targetTypes.All(t => t == typeof(string)))
// Normally we'd return null but throw exception just for unit test to catch
throw new Exception("Invalid targetTypes");
var array = s.Split(new string[] { concatenator }, StringSplitOptions.RemoveEmptyEntries).Cast<object>().ToArray();
var array = s.Split(new string[] { separator }, StringSplitOptions.RemoveEmptyEntries).Cast<object>().ToArray();
for (int i = 0; i < array.Length; i++)
{
var str = array[i] as string;
@ -858,12 +859,12 @@ namespace Xamarin.Forms.Core.UnitTests
source: new RelativeBindingSource(RelativeBindingSourceMode.TemplatedParent)));
cp.SetBinding(ContentPresenter.IsVisibleProperty, new MultiBinding
{
Bindings = new Collection<BindingBase>
{
Bindings = {
new Binding(nameof(ExpanderControl.IsEnabled), source: RelativeBindingSource.TemplatedParent),
new Binding(nameof(ExpanderControl.IsExpanded), source: RelativeBindingSource.TemplatedParent)
},
Converter = new AllTrueMultiConverter()
Converter = new AllTrueMultiConverter(),
FallbackValue = false
});
this.Children.Add(cp);
}

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

@ -403,7 +403,7 @@ namespace Xamarin.Forms.Core.UnitTests
{
var shell = new Shell();
ShellTestPage pagetoTest = new ShellTestPage();
pagetoTest.BindingContext = pagetoTest;
pagetoTest.BindingContext = pagetoTest;
var one = CreateShellItem(pagetoTest, shellContentRoute: "content", templated: useDataTemplates);
shell.Items.Add(one);
ShellTestPage page = null;
@ -1362,10 +1362,10 @@ namespace Xamarin.Forms.Core.UnitTests
var classStyle = new Style(typeof(Grid))
{
Setters = {
new Setter
new Setter
{
Property = VisualStateManager.VisualStateGroupsProperty,
Value = groups
Value = groups
}
},
Class = FlyoutItem.LayoutStyle,
@ -1429,6 +1429,57 @@ namespace Xamarin.Forms.Core.UnitTests
Assert.IsNotNull(item.CurrentItem.CurrentItem);
}
[TestCase("ContentPage")]
[TestCase("ShellItem")]
[TestCase("Shell")]
public void TabBarIsVisible(string test)
{
Shell shell = new Shell();
ContentPage page = new ContentPage();
var shellItem = CreateShellItem(page);
shell.Items.Add(shellItem);
switch (test)
{
case "ContentPage":
Shell.SetTabBarIsVisible(page, false);
break;
case "ShellItem":
Shell.SetTabBarIsVisible(shellItem, false);
break;
case "Shell":
Shell.SetTabBarIsVisible(shell, false);
break;
}
Assert.IsFalse((shellItem as IShellItemController).ShowTabs);
}
[Test]
public void SendStructureChangedFiresWhenAddingItems()
{
Shell shell = new Shell();
shell.Items.Add(CreateShellItem());
int count = 0;
int previousCount = 0;
(shell as IShellController).StructureChanged += (_, __) => count++;
shell.Items.Add(CreateShellItem());
Assert.Greater(count, previousCount, "StructureChanged not fired when adding Shell Item");
previousCount = count;
shell.CurrentItem.Items.Add(CreateShellSection());
Assert.Greater(count, previousCount, "StructureChanged not fired when adding Shell Section");
previousCount = count;
shell.CurrentItem.CurrentItem.Items.Add(CreateShellContent());
Assert.Greater(count, previousCount, "StructureChanged not fired when adding Shell Content");
}
//[Test]
//public void FlyoutItemLabelStyleCanBeChangedAfterRendered()
//{

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

@ -148,7 +148,7 @@ namespace Xamarin.Forms
if (!(Source is RelativeBindingSource relativeSource))
return;
var relativeSourceTarget = this.RelativeSourceTargetOverride ?? targetObject as Element;
var relativeSourceTarget = RelativeSourceTargetOverride ?? targetObject as Element;
if (!(relativeSourceTarget is Element))
throw new InvalidOperationException();

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

@ -1,6 +1,7 @@
using System;
using System.Collections;
using System.Runtime.CompilerServices;
using Xamarin.Forms.Internals;
namespace Xamarin.Forms
{
@ -42,7 +43,6 @@ namespace Xamarin.Forms
set
{
ThrowIfApplied();
_stringFormat = value;
}
}
@ -109,18 +109,12 @@ namespace Xamarin.Forms
protected void ThrowIfApplied()
{
if (IsApplied)
throw new InvalidOperationException("Can not change a binding while it's applied");
throw new InvalidOperationException("Cannot change a binding while it's applied");
}
internal virtual void Apply(bool fromTarget)
{
IsApplied = true;
}
internal virtual void Apply(bool fromTarget) => IsApplied = true;
internal virtual void Apply(object context, BindableObject bindObj, BindableProperty targetProperty, bool fromBindingContextChanged = false)
{
IsApplied = true;
}
internal virtual void Apply(object context, BindableObject bindObj, BindableProperty targetProperty, bool fromBindingContextChanged = false) => IsApplied = true;
internal abstract BindingBase Clone();
@ -129,17 +123,39 @@ namespace Xamarin.Forms
if (value == null && TargetNullValue != null)
return TargetNullValue;
if (StringFormat != null)
return string.Format(StringFormat, value);
if (StringFormat != null && TryFormat(StringFormat, value, out var formatted))
return formatted;
return value;
}
internal virtual object GetTargetValue(object value, Type sourcePropertyType)
internal bool TryFormat(string format, object arg0, out string value)
{
return value;
try {
value = string.Format(format, arg0);
return true;
} catch (FormatException) {
value = null;
Log.Warning("Binding", "FormatException");
return false;
}
}
internal bool TryFormat(string format, object[] args, out string value)
{
try {
value = string.Format(format, args);
return true;
}
catch (FormatException) {
value = null;
Log.Warning("Binding", "FormatException");
return false;
}
}
internal virtual object GetTargetValue(object value, Type sourcePropertyType) => value;
internal static bool TryGetSynchronizedCollection(IEnumerable collection, out CollectionSynchronizationContext synchronizationContext)
{
if (collection == null)
@ -148,9 +164,6 @@ namespace Xamarin.Forms
return SynchronizedCollections.TryGetValue(collection, out synchronizationContext);
}
internal virtual void Unapply(bool fromBindingContextChanged = false)
{
IsApplied = false;
}
internal virtual void Unapply(bool fromBindingContextChanged = false) => IsApplied = false;
}
}

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

@ -10,7 +10,6 @@ namespace Xamarin.Forms
internal static class ExperimentalFlags
{
internal const string StateTriggersExperimental = "StateTriggers_Experimental";
internal const string IndicatorViewExperimental = "IndicatorView_Experimental";
internal const string ShellUWPExperimental = "Shell_UWP_Experimental";
internal const string CarouselViewExperimental = "CarouselView_Experimental";
internal const string SwipeViewExperimental = "SwipeView_Experimental";

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

@ -39,7 +39,7 @@ namespace Xamarin.Forms
public IndicatorView()
{
ExperimentalFlags.VerifyFlagEnabled(nameof(IndicatorView), ExperimentalFlags.IndicatorViewExperimental);
}
public IndicatorShape IndicatorsShape

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

@ -1,72 +0,0 @@
namespace Xamarin.Forms.Internals
{
// This class serves as a "proxy" for the target and the sources,
// with the MultiBinding serving as the bridge between them.
// All the BindingExpression's actually bind between the proxies and the
// target/sources. This avoids the need for what would otherwise be some very
// ugly subclassing or modifications to BindingExpression. And it
// makes it very easy to supported nested MultiBinding's which is
// not possible with WPF.
internal class MultiBindingProxy : BindableObject
{
internal bool SuspendValueChangeNotification { get; private set; }
internal bool IsTarget { get; }
public static readonly BindableProperty ValueProperty = BindableProperty.Create(
nameof(Value),
typeof(object),
typeof(MultiBindingProxy),
null,
propertyChanged:
new BindableProperty.BindingPropertyChangedDelegate(
(obj, oldVal, newVal)=>
(obj as MultiBindingProxy).OnValueChanged(oldVal, newVal)));
internal MultiBindingProxy(MultiBinding multiBinding, bool isTarget)
{
this.MultiBinding = multiBinding;
this.IsTarget = isTarget;
}
public object Value
{
get
{
return GetValue(ValueProperty);
}
set
{
SetValue(ValueProperty, value);
}
}
internal MultiBinding MultiBinding { get; }
internal BindingMode RealizedMode { get; set; }
internal void SetValueSilent(BindableProperty property, object value)
{
bool suspended = this.SuspendValueChangeNotification;
this.SuspendValueChangeNotification = true;
try
{
SetValue(property, value);
}
finally
{
SuspendValueChangeNotification = suspended;
}
}
void OnValueChanged(object oldValue, object newValue)
{
if (this.IsTarget)
// Updates to target value are handled by MultiBinding.Apply
return;
if (!SuspendValueChangeNotification)
this.MultiBinding.ApplyBindingProxyValues(this);
}
}
}

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

@ -1,9 +1,6 @@
using System;
using System.Linq;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using Xamarin.Forms.Internals;
namespace Xamarin.Forms
@ -13,12 +10,12 @@ namespace Xamarin.Forms
{
IMultiValueConverter _converter;
object _converterParameter;
BindingExpression _expression;
IList<BindingBase> _bindings;
BindableProperty _targetProperty;
bool _isApplying;
bool _isCreating;
bool _hasSuccessfullyConverted;
BindableObject _targetObject;
BindableObject _proxyObject;
BindableProperty[] _bpProxies;
bool _applying;
public IMultiValueConverter Converter
{
@ -50,17 +47,16 @@ namespace Xamarin.Forms
}
}
internal List<MultiBindingProxy> SourceProxies { get; private set; }
internal MultiBindingProxy TargetProxy { get; private set; }
internal override BindingBase Clone()
{
return new MultiBinding()
{
var bindingsclone = new List<BindingBase>(Bindings.Count);
foreach (var b in Bindings)
bindingsclone.Add(b.Clone());
return new MultiBinding() {
Converter = Converter,
ConverterParameter = ConverterParameter,
Bindings = new Collection<BindingBase>(this.Bindings),
Bindings = bindingsclone,
FallbackValue = FallbackValue,
Mode = Mode,
TargetNullValue = TargetNullValue,
@ -70,238 +66,147 @@ namespace Xamarin.Forms
internal override void Apply(bool fromTarget)
{
VerifyConverterBeforeApply();
base.Apply(fromTarget);
if (_hasSuccessfullyConverted && this.GetRealizedMode(_targetProperty) == BindingMode.OneTime)
if (_applying)
return;
if (_expression == null)
_expression = new BindingExpression(this, Binding.SelfPath);
if (fromTarget && _isApplying)
base.Apply(fromTarget);
if (this.GetRealizedMode(_targetProperty) == BindingMode.OneTime)
return;
_expression.Apply(fromTarget);
ApplyBindingProxyValues(fromTarget ? TargetProxy : null, false);
}
if (fromTarget && this.GetRealizedMode(_targetProperty) == BindingMode.OneWay)
return;
internal override void Apply(
object context,
BindableObject bindObj,
BindableProperty targetProperty,
bool fromBindingContextChanged = false)
{
VerifyConverterBeforeApply();
base.Apply(context, bindObj, targetProperty, fromBindingContextChanged);
if (IsApplied && fromBindingContextChanged)
if (!fromTarget && this.GetRealizedMode(_targetProperty) == BindingMode.OneWayToSource)
return;
if (!fromTarget)
{
bool childContextChanged = false;
foreach (var proxy in SourceProxies)
{
if (!object.ReferenceEquals(proxy.BindingContext, context))
var value = GetSourceValue(GetValueArray(), _targetProperty.ReturnType);
if (value != Binding.DoNothing) {
_applying = true;
_targetObject.SetValueCore(_targetProperty, value, SetValueFlags.ClearDynamicResource, BindableObject.SetValuePrivateFlags.Default | BindableObject.SetValuePrivateFlags.Converted);
_applying = false;
}
}
else
{
try {
_applying = true;
//https://docs.microsoft.com/en-us/dotnet/api/system.windows.data.imultivalueconverter.convertback?view=netframework-4.8#remarks
if (!(GetTargetValue(_targetObject.GetValue(_targetProperty), null) is object[] values)) //converter failed
return;
for (var i = 0; i < Math.Min(_bpProxies.Length, values.Length); i++)
{
childContextChanged = true;
proxy.SetValueSilent(Element.BindingContextProperty, context);
if (ReferenceEquals(values[i], Binding.DoNothing) || ReferenceEquals(values[i], BindableProperty.UnsetValue))
continue;
_proxyObject.SetValueCore(_bpProxies[i], values[i], SetValueFlags.None);
}
}
if ( childContextChanged )
ApplyBindingProxyValues(null, true);
finally {
_applying = false;
}
}
}
internal override void Apply(object context, BindableObject targetObject, BindableProperty targetProperty, bool fromBindingContextChanged = false)
{
if (_bindings == null)
throw new InvalidOperationException("Bindings is null");
base.Apply(context, targetObject, targetProperty, fromBindingContextChanged);
if (!ReferenceEquals(_targetObject, targetObject)) {
_targetObject = targetObject;
_proxyObject = new ProxyElement() { Parent = targetObject as Element };
_targetProperty = targetProperty;
if (_bpProxies == null) {
_bpProxies = new BindableProperty[Bindings.Count];
_applying = true;
var bindingMode = Mode == BindingMode.Default ? targetProperty.DefaultBindingMode : Mode;
for (var i = 0; i < Bindings.Count; i++) {
var binding = Bindings[i];
binding.RelativeSourceTargetOverride = targetObject as Element;
var bp = _bpProxies[i] = BindableProperty.Create($"mb-proxy{i}", typeof(object), typeof(MultiBinding), null, bindingMode, propertyChanged: OnBindingChanged);
_proxyObject.SetBinding(bp, binding);
}
_applying = false;
}
}
_proxyObject.BindingContext = context;
if (this.GetRealizedMode(_targetProperty) == BindingMode.OneWayToSource)
return;
}
_targetProperty = targetProperty;
if (_expression == null)
_expression = new BindingExpression(this, nameof(MultiBindingProxy.Value));
CreateBindingProxies(bindObj, context);
var value = GetSourceValue(GetValueArray(), _targetProperty.ReturnType);
if (value != Binding.DoNothing) {
_applying = true;
_targetObject.SetValueCore(_targetProperty, value, SetValueFlags.ClearDynamicResource, BindableObject.SetValuePrivateFlags.Default | BindableObject.SetValuePrivateFlags.Converted);
_applying = false;
}
}
_isApplying = true;
try
{
ApplyBindingProxyValues(TargetProxy, reapplyExpression: false, firstApplication: true);
_expression.Apply(TargetProxy, bindObj, targetProperty);
if (this.GetRealizedMode(_targetProperty) == BindingMode.OneWayToSource &&
this.FallbackValue != null)
bindObj.SetValue(targetProperty, this.FallbackValue);
}
finally
{
_isApplying = false;
class ProxyElement : Element
{
}
object[] GetValueArray()
{
var valuearray = new object[_bpProxies.Length];
for (var i = 0; i < _bpProxies.Length; i++)
valuearray[i] = _proxyObject.GetValue(_bpProxies[i]);
return valuearray;
}
internal override object GetSourceValue(object value, Type targetPropertyType)
{
var valuearray = value as object[];
if (valuearray != null && Converter != null)
value = Converter.Convert(valuearray, targetPropertyType, ConverterParameter, CultureInfo.CurrentUICulture);
if (valuearray != null && StringFormat != null && TryFormat(StringFormat, valuearray, out var formatted))
return formatted;
if (ReferenceEquals(BindableProperty.UnsetValue, value))
return FallbackValue;
return base.GetSourceValue(value, targetPropertyType);
}
internal override object GetTargetValue(object value, Type sourcePropertyType)
{
if (Converter != null) {
var values = GetValueArray();
var types = new Type[_bpProxies.Length];
for (var i = 0; i < _bpProxies.Length; i++)
types[i] = values[i]?.GetType() ?? typeof(object);
return Converter.ConvertBack(value, types, ConverterParameter, CultureInfo.CurrentUICulture);
}
return base.GetTargetValue(value, sourcePropertyType);
}
void OnBindingChanged(BindableObject bindable, object oldValue, object newValue)
{
if (!_applying)
Apply(fromTarget: false);
}
internal override void Unapply(bool fromBindingContextChanged = false)
{
if (fromBindingContextChanged && IsApplied)
return;
if (!fromBindingContextChanged) {
if (_bpProxies != null && _proxyObject != null)
foreach (var proxybp in _bpProxies)
_proxyObject.RemoveBinding(proxybp);
_bpProxies = null;
_proxyObject = null;
}
base.Unapply(fromBindingContextChanged: fromBindingContextChanged);
if (_expression != null)
_expression.Unapply();
TargetProxy.RemoveBinding(MultiBindingProxy.ValueProperty);
if (this.SourceProxies?.Count > 0)
{
foreach (var proxy in this.SourceProxies)
proxy.RemoveBinding(MultiBindingProxy.ValueProperty);
}
TargetProxy = null;
SourceProxies = null;
}
internal void ApplyBindingProxyValues(MultiBindingProxy trigger, bool reapplyExpression = true, bool firstApplication = false)
{
if (_isCreating)
return;
BindingMode mode = this.GetRealizedMode(_targetProperty);
bool convertBackFailed = false;
if (trigger?.IsTarget == true &&
!trigger.SuspendValueChangeNotification &&
(!firstApplication || mode == BindingMode.OneWayToSource) &&
(mode == BindingMode.TwoWay || mode == BindingMode.OneWayToSource))
{
// triggered because the target property was updated
convertBackFailed = !ApplyTargetValueUpdate();
}
if (mode != BindingMode.OneWayToSource &&
!convertBackFailed &&
(trigger?.IsTarget != true || !TargetProxy.SuspendValueChangeNotification))
{
object newTargetValue = BindableProperty.UnsetValue;
if (this.Converter != null)
{
newTargetValue = this.Converter.Convert(
SourceProxies.Select(p => p.Value).ToArray(),
_targetProperty.ReturnType,
this.ConverterParameter,
CultureInfo.CurrentUICulture);
if (newTargetValue == Binding.DoNothing)
return;
}
if (newTargetValue == BindableProperty.UnsetValue)
newTargetValue = this.FallbackValue ?? _targetProperty.DefaultValue;
else if (newTargetValue == null)
newTargetValue = this.TargetNullValue ?? _targetProperty.DefaultValue;
else
_hasSuccessfullyConverted = true;
TargetProxy.SetValueSilent(MultiBindingProxy.ValueProperty, newTargetValue);
}
if (reapplyExpression)
{
bool wasApplying = _isApplying;
_isApplying = true;
_expression.Apply();
_isApplying = wasApplying;
}
return;
}
bool ApplyTargetValueUpdate()
{
var types = SourceProxies
.Select(p => p.Value?.GetType() ?? _targetProperty.ReturnType)
.ToArray();
var convertedValues = this.Converter?.ConvertBack(
TargetProxy.Value,
types,
this.ConverterParameter,
CultureInfo.CurrentUICulture);
if (convertedValues == null || convertedValues.Any(val=>object.ReferenceEquals(val, BindableProperty.UnsetValue)))
{
// https://docs.microsoft.com/en-us/dotnet/api/system.windows.data.imultivalueconverter.convertback?view=netframework-4.8
// Return null to indicate that the converter cannot perform the
// conversion or that it does not support conversion in this direction.
// Return DependencyProperty.UnsetValue at position i to indicate that
// the converter is unable to provide a value for the source binding at
// index i, and that no value is to be set on it.
return false;
}
int count = Math.Min(convertedValues.Length, this.SourceProxies.Count);
for (int i = 0; i < count; i++)
{
// https://docs.microsoft.com/en-us/dotnet/api/system.windows.data.imultivalueconverter.convertback?view=netframework-4.8
// Return DoNothing at position i to indicate that no value is to
// be set on the source binding at index i.
if (convertedValues[i] == Binding.DoNothing)
continue;
var childMode = this.SourceProxies[i].RealizedMode;
if (childMode != BindingMode.TwoWay && childMode != BindingMode.OneWayToSource)
continue;
this.SourceProxies[i].SetValueSilent(MultiBindingProxy.ValueProperty, convertedValues[i]);
}
return true;
}
void CreateBindingProxies(BindableObject target, object context)
{
_hasSuccessfullyConverted = false;
_isCreating = true;
try
{
TargetProxy = new MultiBindingProxy(this, true);
SourceProxies = new List<MultiBindingProxy>();
if (this.Bindings.Count == 0)
return;
var mode = this.GetRealizedMode(_targetProperty);
if (mode == BindingMode.OneWayToSource)
TargetProxy.Value = this.FallbackValue;
foreach (var binding in _bindings)
{
var proxy = new MultiBindingProxy(this, false);
proxy.BindingContext = context;
// Bind proxy's Value property using the source binding settings
var proxyBinding = binding.Clone();
// Ensures that RelativeSource bindings resolve using the
// MultiBinding's BindableObject target rather than the proxy.
if (target is MultiBindingProxy)
proxyBinding.RelativeSourceTargetOverride = this.RelativeSourceTargetOverride;
else if (target is Element e)
proxyBinding.RelativeSourceTargetOverride = e;
// OneWayToSource, OneTime, or OneWay mode on the MultiBinding effectively
// override the childrens' modes
if ( mode == BindingMode.OneWayToSource ||
mode == BindingMode.OneTime ||
mode == BindingMode.OneWay ||
proxyBinding.Mode == BindingMode.Default)
proxyBinding.Mode = mode;
proxy.SetBinding(MultiBindingProxy.ValueProperty, proxyBinding);
proxy.RealizedMode = proxyBinding.Mode;
SourceProxies.Add(proxy);
}
}
finally
{
_isCreating = false;
}
}
void VerifyConverterBeforeApply()
{
if (this.Converter == null)
throw new InvalidOperationException($"{nameof(MultiBinding)} requires {nameof(Converter)} be set.");
}
}
}

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

@ -9,5 +9,6 @@ namespace Xamarin.Forms
ReadOnlyCollection<ShellSection> GetItems();
event NotifyCollectionChangedEventHandler ItemsCollectionChanged;
bool ShowTabs { get; }
}
}

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

@ -146,9 +146,9 @@ namespace Xamarin.Forms
BindableProperty.CreateAttached("UnselectedColor", typeof(Color), typeof(Shell), Color.Default,
propertyChanged: OnColorValueChanged);
public static readonly BindableProperty FlyoutBackdropColorProperty =
BindableProperty.CreateAttached("FlyoutBackdropColor", typeof(Color), typeof(Shell), Color.Default,
propertyChanged: OnColorValueChanged);
//public static readonly BindableProperty FlyoutBackdropColorProperty =
// BindableProperty.CreateAttached("FlyoutBackdropColor", typeof(Color), typeof(Shell), Color.Default,
// propertyChanged: OnColorValueChanged);
public static Color GetBackgroundColor(BindableObject obj) => (Color)obj.GetValue(BackgroundColorProperty);
public static void SetBackgroundColor(BindableObject obj, Color value) => obj.SetValue(BackgroundColorProperty, value);
@ -180,8 +180,8 @@ namespace Xamarin.Forms
public static Color GetUnselectedColor(BindableObject obj) => (Color)obj.GetValue(UnselectedColorProperty);
public static void SetUnselectedColor(BindableObject obj, Color value) => obj.SetValue(UnselectedColorProperty, value);
public static Color GetFlyoutBackdropColor(BindableObject obj) => (Color)obj.GetValue(FlyoutBackdropColorProperty);
public static void SetFlyoutBackdropColor(BindableObject obj, Color value) => obj.SetValue(FlyoutBackdropColorProperty, value);
//public static Color GetFlyoutBackdropColor(BindableObject obj) => (Color)obj.GetValue(FlyoutBackdropColorProperty);
//public static void SetFlyoutBackdropColor(BindableObject obj, Color value) => obj.SetValue(FlyoutBackdropColorProperty, value);
static void OnColorValueChanged(BindableObject bindable, object oldValue, object newValue)
{
@ -843,11 +843,11 @@ namespace Xamarin.Forms
set => SetValue(FlyoutBackgroundColorProperty, value);
}
public Color FlyoutBackdropColor
{
get => (Color)GetValue(FlyoutBackdropColorProperty);
set => SetValue(FlyoutBackdropColorProperty, value);
}
//public Color FlyoutBackdropColor
//{
// get => (Color)GetValue(FlyoutBackdropColorProperty);
// set => SetValue(FlyoutBackdropColorProperty, value);
//}
public FlyoutBehavior FlyoutBehavior
{
@ -1218,15 +1218,14 @@ namespace Xamarin.Forms
(o) => rootItem = rootItem ?? o as ShellItem);
}
T GetEffectiveValue<T>(BindableProperty property, T defaultValue)
internal T GetEffectiveValue<T>(BindableProperty property, T defaultValue)
{
return GetEffectiveValue(property, () => defaultValue, null);
return GetEffectiveValue<T>(property, () => defaultValue, null);
}
T GetEffectiveValue<T>(BindableProperty property, Func<T> defaultValue, Action<Element> observer)
{
Element element = GetVisiblePage() ?? CurrentContent;
internal T GetEffectiveValue<T>(BindableProperty property, Func<T> defaultValue, Action<Element> observer, Element element = null)
{
element = element ?? GetVisiblePage() ?? CurrentContent;
while (element != this && element != null)
{
observer?.Invoke(element);

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

@ -18,7 +18,7 @@ namespace Xamarin.Forms
Shell.TabBarUnselectedColorProperty,
Shell.TitleColorProperty,
Shell.UnselectedColorProperty,
Shell.FlyoutBackdropColorProperty
//Shell.FlyoutBackdropColorProperty
};
Color?[] _colorArray = new Color?[s_ingestArray.Length];
@ -43,7 +43,7 @@ namespace Xamarin.Forms
public Color UnselectedColor => _colorArray[9].Value;
public Color FlyoutBackdropColor => _colorArray[10].Value;
//public Color FlyoutBackdropColor => _colorArray[10].Value;
Color IShellAppearanceElement.EffectiveTabBarBackgroundColor =>
!TabBarBackgroundColor.IsDefault ? TabBarBackgroundColor : BackgroundColor;

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

@ -93,6 +93,23 @@ namespace Xamarin.Forms
remove { ((ShellSectionCollection)Items).VisibleItemsChanged -= value; }
}
bool IShellItemController.ShowTabs
{
get
{
var displayedPage = CurrentItem?.DisplayedPage;
if (displayedPage == null)
return true;
Shell shell = Parent as Shell;
if (shell == null)
return true;
bool defaultShow = ShellItemController.GetItems().Count > 1;
return shell.GetEffectiveValue<bool>(Shell.TabBarIsVisibleProperty, () => defaultShow, null, displayedPage);
}
}
#endregion IShellItemController
#region IPropertyPropagationController

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

@ -277,7 +277,7 @@ namespace Xamarin.Forms
internal override ReadOnlyCollection<Element> LogicalChildrenInternal => _logicalChildrenReadOnly ?? (_logicalChildrenReadOnly = new ReadOnlyCollection<Element>(_logicalChildren));
Page DisplayedPage
internal Page DisplayedPage
{
get { return _displayedPage; }
set

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

@ -59,9 +59,9 @@
</ProjectReference>
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'MonoAndroid10.0'">
<PackageReference Include="Xamarin.AndroidX.Lifecycle.LiveData" Version="2.1.0" />
<PackageReference Include="Xamarin.Google.Android.Material" Version="1.0.0" />
<PackageReference Include="Xamarin.AndroidX.Legacy.Support.V4" Version="1.0.0" />
<PackageReference Include="Xamarin.AndroidX.Lifecycle.LiveData" Version="2.1.0.1" />
<PackageReference Include="Xamarin.Google.Android.Material" Version="1.0.0.1" />
<PackageReference Include="Xamarin.AndroidX.Legacy.Support.V4" Version="1.0.0.1" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'MonoAndroid90'">
<PackageReference Include="Xamarin.Android.Support.Design" Version="28.0.0.3" />

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

@ -24,11 +24,11 @@
</ProjectReference>
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'MonoAndroid10.0'">
<PackageReference Include="Xamarin.AndroidX.Lifecycle.LiveData" Version="2.1.0" />
<PackageReference Include="Xamarin.Google.Android.Material" Version="1.0.0" />
<PackageReference Include="Xamarin.AndroidX.Legacy.Support.V4" Version="1.0.0" />
<PackageReference Include="Xamarin.AndroidX.Lifecycle.LiveData" Version="2.1.0.1" />
<PackageReference Include="Xamarin.Google.Android.Material" Version="1.0.0.1" />
<PackageReference Include="Xamarin.AndroidX.Legacy.Support.V4" Version="1.0.0.1" />
<PackageReference Include="Xamarin.AndroidX.Migration">
<Version>1.0.0</Version>
<Version>1.0.0.1</Version>
</PackageReference>
</ItemGroup>
<ItemGroup>

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

@ -19,8 +19,8 @@
<AndroidResource Include="Resources\**\*" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'MonoAndroid10.0'">
<PackageReference Include="Xamarin.AndroidX.Lifecycle.LiveData" Version="2.1.0" />
<PackageReference Include="Xamarin.Google.Android.Material" Version="1.0.0" />
<PackageReference Include="Xamarin.AndroidX.Lifecycle.LiveData" Version="2.1.0.1" />
<PackageReference Include="Xamarin.Google.Android.Material" Version="1.0.0.1" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'MonoAndroid90'">
<PackageReference Include="Xamarin.Android.Support.v7.AppCompat" Version="28.0.0.3" />

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

@ -30,10 +30,10 @@
</ProjectReference>
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'MonoAndroid10.0'">
<PackageReference Include="Xamarin.AndroidX.Lifecycle.LiveData" Version="2.1.0" />
<PackageReference Include="Xamarin.AndroidX.Legacy.Support.V4" Version="1.0.0" />
<PackageReference Include="Xamarin.AndroidX.Lifecycle.LiveData" Version="2.1.0.1" />
<PackageReference Include="Xamarin.AndroidX.Legacy.Support.V4" Version="1.0.0.1" />
<PackageReference Include="Xamarin.AndroidX.Migration">
<Version>1.0.0</Version>
<Version>1.0.0.1</Version>
</PackageReference>
</ItemGroup>
<ItemGroup>

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

@ -22,10 +22,10 @@ namespace Xamarin.Forms.Platform.Android
void IAppearanceObserver.OnAppearanceChanged(ShellAppearance appearance)
{
if (appearance == null)
//if (appearance == null)
UpdateScrimColor(Color.Default);
else
UpdateScrimColor(appearance.FlyoutBackdropColor);
//else
// UpdateScrimColor(appearance.FlyoutBackdropColor);
}
#endregion IAppearanceObserver

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

@ -56,6 +56,7 @@ namespace Xamarin.Forms.Platform.Android
BottomNavigationViewTracker _bottomNavigationTracker;
BottomSheetDialog _bottomSheetDialog;
bool _disposed;
public IShellItemController ShellItemController => ShellItem;
public ShellItemRenderer(IShellContext shellContext) : base(shellContext)
{
@ -418,7 +419,7 @@ namespace Xamarin.Forms.Platform.Android
if (DisplayedPage == null)
return;
bool visible = Shell.GetTabBarIsVisible(DisplayedPage);
bool visible = ShellItemController.ShowTabs;
using (var menu = _bottomView.Menu)
{
if (menu.Size() == 1)

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

@ -55,9 +55,9 @@
<Reference Include="System.Net.Http" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'MonoAndroid10.0'">
<PackageReference Include="Xamarin.AndroidX.Lifecycle.LiveData" Version="2.1.0" />
<PackageReference Include="Xamarin.Google.Android.Material" Version="1.0.0" />
<PackageReference Include="Xamarin.AndroidX.Legacy.Support.V4" Version="1.0.0" />
<PackageReference Include="Xamarin.AndroidX.Lifecycle.LiveData" Version="2.1.0.1" />
<PackageReference Include="Xamarin.Google.Android.Material" Version="1.0.0.1" />
<PackageReference Include="Xamarin.AndroidX.Legacy.Support.V4" Version="1.0.0.1" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'MonoAndroid90'">
<PackageReference Include="Xamarin.Android.Support.Design" Version="28.0.0.3" />

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

@ -34,6 +34,7 @@ namespace Xamarin.Forms.Platform.UWP
internal ShellRenderer ShellContext { get; set; }
IShellItemController ShellItemController => ShellItem;
IShellController ShellController => ShellContext?.Shell;
public ShellItemRenderer(ShellRenderer shellContext)
{
@ -241,6 +242,7 @@ namespace Xamarin.Forms.Platform.UWP
{
shellItem.PropertyChanged += OnShellItemPropertyChanged;
ShellItemController.ItemsCollectionChanged += OnShellItemsChanged;
ShellController.StructureChanged += OnShellStructureChanged;
foreach (var shellSection in ShellItemController.GetItems())
{
HookChildEvents(shellSection);
@ -255,6 +257,8 @@ namespace Xamarin.Forms.Platform.UWP
{
UnhookChildEvents(shellSection);
}
ShellController.StructureChanged -= OnShellStructureChanged;
ShellItemController.ItemsCollectionChanged -= OnShellItemsChanged;
ShellItem.PropertyChanged -= OnShellItemPropertyChanged;
ShellSection = null;
@ -299,6 +303,11 @@ namespace Xamarin.Forms.Platform.UWP
SwitchSection(ShellNavigationSource.ShellSectionChanged, newSection, null, oldSection != null);
}
void OnShellStructureChanged(object sender, EventArgs e)
{
UpdateBottomBarVisibility();
}
void SwitchSection(ShellNavigationSource source, ShellSection section, Page page, bool animate = true)
{
if (section == null)
@ -365,7 +374,8 @@ namespace Xamarin.Forms.Platform.UWP
void UpdateBottomBarVisibility()
{
_BottomBar.Visibility = DisplayedPage == null || Shell.GetTabBarIsVisible(DisplayedPage) ? Visibility.Visible : Visibility.Collapsed;
bool isVisible = ShellItemController?.ShowTabs ?? false;
_BottomBar.Visibility = isVisible ? Visibility.Visible : Visibility.Collapsed;
}
void UpdateToolbar()

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

@ -171,10 +171,10 @@ namespace Xamarin.Forms.Platform.UWP
{
UpdateFlyoutBackgroundColor();
}
else if (e.PropertyName == Shell.FlyoutBackdropColorProperty.PropertyName)
{
UpdateFlyoutBackdropColor();
}
//else if (e.PropertyName == Shell.FlyoutBackdropColorProperty.PropertyName)
//{
// UpdateFlyoutBackdropColor();
//}
}
protected virtual void UpdateFlyoutBackdropColor()
@ -182,7 +182,7 @@ namespace Xamarin.Forms.Platform.UWP
var splitView = ShellSplitView;
if (splitView != null)
{
splitView.FlyoutBackdropColor = _shell.FlyoutBackdropColor;
//splitView.FlyoutBackdropColor = _shell.FlyoutBackdropColor;
if (IsPaneOpen)
ShellSplitView.UpdateFlyoutBackdropColor();
}

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

@ -79,12 +79,7 @@ namespace Xamarin.Forms.Platform.iOS
if (Element.BackgroundColor == Color.Default)
_actualView.Layer.BackgroundColor = ColorExtensions.BackgroundColor.CGColor;
else
{
// BackgroundColor gets set on the base class too which messes with
// the corner radius, shadow, etc. so override that behaviour here
BackgroundColor = null;
_actualView.Layer.BackgroundColor = Element.BackgroundColor.ToCGColor();
}
if (Element.BorderColor == Color.Default)
_actualView.Layer.BorderColor = UIColor.Clear.CGColor;

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

@ -14,10 +14,10 @@ namespace Xamarin.Forms.Platform.iOS
void IAppearanceObserver.OnAppearanceChanged(ShellAppearance appearance)
{
if (appearance == null)
//if (appearance == null)
_backdropColor = Color.Default;
else
_backdropColor = appearance.FlyoutBackdropColor;
//else
// _backdropColor = appearance.FlyoutBackdropColor;
UpdateTapoffViewBackgroundColor();
}

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

@ -206,7 +206,7 @@ namespace Xamarin.Forms.Platform.iOS
GoTo(ShellItem.CurrentItem);
}
SetTabBarHidden(ViewControllers.Length == 1);
UpdateTabBarHidden();
}
protected virtual void OnShellItemSet(ShellItem shellItem)
@ -271,9 +271,7 @@ namespace Xamarin.Forms.Platform.iOS
ViewControllers = viewControllers;
CustomizableViewControllers = Array.Empty<UIViewController>();
// No sense showing a bar that has a single icon
if (ViewControllers.Length == 1)
SetTabBarHidden(true);
UpdateTabBarHidden();
// Make sure we are at the right item
GoTo(ShellItem.CurrentItem);
@ -370,21 +368,12 @@ namespace Xamarin.Forms.Platform.iOS
return null;
}
void SetTabBarHidden(bool hidden)
{
TabBar.Hidden = hidden;
}
void UpdateTabBarHidden()
{
if (_displayedPage == null || ShellItem == null)
if (ShellItemController == null)
return;
var hidden = !Shell.GetTabBarIsVisible(_displayedPage);
if (ShellItemController.GetItems().Count > 1)
{
SetTabBarHidden(hidden);
}
TabBar.Hidden = !ShellItemController.ShowTabs;
}
}
}
}

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

@ -661,6 +661,7 @@ Global
{C7131F14-274F-4B55-ACA9-E81731AD012F}.Debug|ARM64.ActiveCfg = Debug|iPhone
{C7131F14-274F-4B55-ACA9-E81731AD012F}.Debug|iPhone.ActiveCfg = Debug|iPhone
{C7131F14-274F-4B55-ACA9-E81731AD012F}.Debug|iPhone.Build.0 = Debug|iPhone
{C7131F14-274F-4B55-ACA9-E81731AD012F}.Debug|iPhone.Deploy.0 = Debug|iPhone
{C7131F14-274F-4B55-ACA9-E81731AD012F}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
{C7131F14-274F-4B55-ACA9-E81731AD012F}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
{C7131F14-274F-4B55-ACA9-E81731AD012F}.Debug|x64.ActiveCfg = Debug|iPhoneSimulator

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

@ -43,10 +43,10 @@ var releaseChannelArg = Argument("CHANNEL", "Stable");
releaseChannelArg = EnvironmentVariable("CHANNEL") ?? releaseChannelArg;
var teamProject = Argument("TeamProject", "");
bool buildForVS2017 = Convert.ToBoolean(Argument("buildForVS2017", "false"));
string agentName = EnvironmentVariable("Agent_Name", "");
string agentName = EnvironmentVariable("AGENT_NAME", "");
bool isHostedAgent = agentName.StartsWith("Azure Pipelines");
bool isCIBuild = !String.IsNullOrWhiteSpace(agentName);
string artifactStagingDirectory = Argument("Build_ArtifactStagingDirectory", (string)null) ?? EnvironmentVariable("Build.ArtifactStagingDirectory") ?? EnvironmentVariable("Build_ArtifactStagingDirectory") ?? ".";
string artifactStagingDirectory = EnvironmentVariable("BUILD_ARTIFACTSTAGINGDIRECTORY", ".");
var ANDROID_HOME = EnvironmentVariable("ANDROID_HOME") ??
(IsRunningOnWindows () ? "C:\\Program Files (x86)\\Android\\android-sdk\\" : "");
@ -89,9 +89,9 @@ Information ("configuration: {0}", configuration);
Information ("ANDROID_HOME: {0}", ANDROID_HOME);
Information ("Team Project: {0}", teamProject);
Information ("buildForVS2017: {0}", buildForVS2017);
Information ("Agent.Name: {0}", EnvironmentVariable("Agent_Name"));
Information ("Agent.Name: {0}", agentName);
Information ("isCIBuild: {0}", isCIBuild);
Information ("artifactStagingDirectory: {0}", artifactStagingDirectory);
var releaseChannel = ReleaseChannel.Stable;
if(releaseChannelArg == "Preview")
@ -488,6 +488,19 @@ Task("Restore")
}
});
Task("WriteGoogleMapsAPIKey")
.Description("Write GoogleMapsAPIKey to Android Control Gallery")
.Does(() =>
{
string GoogleMapsAPIKey = Argument("GoogleMapsAPIKey", "");
if(!String.IsNullOrWhiteSpace(GoogleMapsAPIKey))
{
Information("Writing GoogleMapsAPIKey");
System.IO.File.WriteAllText("Xamarin.Forms.ControlGallery.Android/Properties/MapsKey.cs", "[assembly: Android.App.MetaData(\"com.google.android.maps.v2.API_KEY\", Value = \"" + GoogleMapsAPIKey + "\")]");
}
});
Task("BuildForNuget")
.Description("Builds all necessary projects to create Nuget Packages")
.Does(() =>
@ -500,7 +513,6 @@ Task("BuildForNuget")
};
msbuildSettings.BinaryLogger = binaryLogger;
msbuildSettings.ArgumentCustomization = args => args.Append("/nowarn:VSX1000");
binaryLogger.FileName = $"{artifactStagingDirectory}/win-{configuration}.binlog";
MSBuild("./Xamarin.Forms.sln", msbuildSettings);
@ -586,6 +598,56 @@ Task("VSMAC")
StartProcess("open", new ProcessSettings{ Arguments = "Xamarin.Forms.sln" });
});
Task("cg-android")
.Description("Builds Android Control Gallery")
.IsDependentOn("WriteGoogleMapsAPIKey")
.IsDependentOn("BuildTasks")
.Does(() =>
{
var buildSettings = GetMSBuildSettings();
if(isCIBuild)
{
buildSettings = buildSettings.WithTarget("Rebuild").WithTarget("SignAndroidPackage");
var binaryLogger = new MSBuildBinaryLogSettings {
Enabled = true
};
buildSettings.BinaryLogger = binaryLogger;
binaryLogger.FileName = $"{artifactStagingDirectory}/android-{ANDROID_RENDERERS}.binlog";
}
else
{
buildSettings = buildSettings.WithRestore();
}
MSBuild("./Xamarin.Forms.ControlGallery.Android/Xamarin.Forms.ControlGallery.Android.csproj", buildSettings);
});
Task("cg-android-vs")
.Description("Builds Android Control Gallery and open VS")
.IsDependentOn("cg-android")
.Does(() =>
{
StartVisualStudio();
});
Task("cg-ios")
.Description("Builds iOS Control Gallery and open VS")
.IsDependentOn("BuildTasks")
.Does(() =>
{
MSBuild("./Xamarin.Forms.ControlGallery.iOS/Xamarin.Forms.ControlGallery.iOS.csproj", GetMSBuildSettings().WithRestore());
});
Task("cg-ios-vs")
.Description("Builds iOS Control Gallery and open VS")
.IsDependentOn("cg-ios")
.Does(() =>
{
StartVisualStudio();
});
/*
Task("Deploy")
.IsDependentOn("DeployiOS")
@ -613,6 +675,27 @@ Task("DeployAndroid")
AmStartActivity("AndroidControlGallery.AndroidControlGallery/md546303760447087909496d02dc7b17ae8.Activity1");
});
Task("_PrintEnvironmentVariables")
.Does(() =>
{
var envVars = EnvironmentVariables();
string path;
if (envVars.TryGetValue("PATH", out path))
{
Information("Path: {0}", path);
}
foreach(var envVar in envVars)
{
Information(
"Key: {0}\tValue: \"{1}\"",
envVar.Key,
envVar.Value
);
}
});
//////////////////////////////////////////////////////////////////////
// TASK TARGETS
//////////////////////////////////////////////////////////////////////
@ -627,6 +710,16 @@ Task("Default")
RunTarget(target);
void StartVisualStudio(string sln = "Xamarin.Forms.sln")
{
if(isCIBuild)
return;
if(IsRunningOnWindows())
StartProcess("start", new ProcessSettings{ Arguments = "Xamarin.Forms.sln" });
else
StartProcess("open", new ProcessSettings{ Arguments = "Xamarin.Forms.sln" });
}
MSBuildSettings GetMSBuildSettings()
{

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

@ -94,18 +94,12 @@ jobs:
feedsToUse: config
nugetConfigPath: 'DevopsNuget.config'
- task: MSBuild@1
displayName: 'Build ${{ parameters.buildTaskPath }}'
inputs:
solution: ${{ parameters.buildTaskPath }}
configuration: ${{ parameters.buildConfiguration }}
- task: MSBuild@1
- task: Bash@3
displayName: 'Build Android $(renderers)'
inputs:
solution: ${{ parameters.androidProjectPath }}
configuration: ${{ parameters.buildConfiguration }}
msbuildArguments: '/t:"Rebuild;SignAndroidPackage" /p:ANDROID_RENDERERS="$(renderers)" /bl:$(Build.ArtifactStagingDirectory)/android-$(renderers)-2017_$(buildForVS2017).binlog'
targetType: 'filePath'
filePath: 'build.sh'
arguments: --target cg-android --ANDROID_RENDERERS="$(renderers)" --GoogleMapsAPIKey="$(GoogleMapsAPIKey)"
- task: CopyFiles@2
displayName: 'Copy $(renderers)'