зеркало из https://github.com/DeGsoft/maui-linux.git
Merge branch '4.3.0'
This commit is contained in:
Коммит
151bdb5ebf
|
@ -18,7 +18,7 @@
|
|||
</group>
|
||||
<group targetFramework="MonoAndroid81">
|
||||
<dependency id="Xamarin.GooglePlayServices.Maps" version="60.1142.1"/>
|
||||
<dependency id="Xamarin.Android.Support.v7.AppCompat" version="28.0.0.1"/>
|
||||
<dependency id="Xamarin.Android.Support.v7.AppCompat" version="28.0.0.3"/>
|
||||
<dependency id="Xamarin.Forms" version="$version$"/>
|
||||
</group>
|
||||
<group targetFramework="tizen40">
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
<dependency id="Xamarin.Forms" version="$version$"/>
|
||||
</group>
|
||||
<group targetFramework="MonoAndroid90">
|
||||
<dependency id="Xamarin.Android.Support.Design" version="28.0.0.1"/>
|
||||
<dependency id="Xamarin.Android.Support.v7.AppCompat" version="28.0.0.1"/>
|
||||
<dependency id="Xamarin.Android.Support.Design" version="28.0.0.3"/>
|
||||
<dependency id="Xamarin.Android.Support.v7.AppCompat" version="28.0.0.3"/>
|
||||
</group>
|
||||
<group targetFramework="Xamarin.iOS10">
|
||||
<dependency id="Xamarin.iOS.MaterialComponents" version="72.2.0.1"/>
|
||||
|
|
|
@ -14,11 +14,11 @@
|
|||
<copyright>© Microsoft Corporation. All rights reserved.</copyright>
|
||||
<dependencies>
|
||||
<group targetFramework="MonoAndroid81">
|
||||
<dependency id="Xamarin.Android.Support.v4" version="28.0.0.1"/>
|
||||
<dependency id="Xamarin.Android.Support.Design" version="28.0.0.1"/>
|
||||
<dependency id="Xamarin.Android.Support.v7.AppCompat" version="28.0.0.1"/>
|
||||
<dependency id="Xamarin.Android.Support.v7.CardView" version="28.0.0.1"/>
|
||||
<dependency id="Xamarin.Android.Support.CustomTabs" version="28.0.0.1"/>
|
||||
<dependency id="Xamarin.Android.Support.v4" version="28.0.0.3"/>
|
||||
<dependency id="Xamarin.Android.Support.Design" version="28.0.0.3"/>
|
||||
<dependency id="Xamarin.Android.Support.v7.AppCompat" version="28.0.0.3"/>
|
||||
<dependency id="Xamarin.Android.Support.v7.CardView" version="28.0.0.3"/>
|
||||
<dependency id="Xamarin.Android.Support.CustomTabs" version="28.0.0.3"/>
|
||||
</group>
|
||||
<group targetFramework="uap10.0">
|
||||
<dependency id="NETStandard.Library" version="2.0.1"/>
|
||||
|
|
|
@ -113,6 +113,7 @@
|
|||
OptimizeIL = "true"
|
||||
DebugSymbols = "$(DebugSymbols)"
|
||||
DebugType = "$(DebugType)"
|
||||
ValidateOnly = "$(XFXamlCValidateOnly)"
|
||||
KeepXamlResources = "$(XFKeepXamlResources)" />
|
||||
<Touch Files="$(IntermediateOutputPath)XamlC.stamp" AlwaysCreate="True" />
|
||||
<ItemGroup>
|
||||
|
|
|
@ -113,8 +113,8 @@
|
|||
<Project>{e1586ce6-8eac-4388-a15a-1aabf108b5f8}</Project>
|
||||
<Name>Xamarin.Forms.Material.Android</Name>
|
||||
</ProjectReference>
|
||||
<PackageReference Include="Xamarin.Android.Support.v4" Version="28.0.0.1" />
|
||||
<PackageReference Include="Xamarin.Android.Support.v7.RecyclerView" Version="28.0.0.1" />
|
||||
<PackageReference Include="Xamarin.Android.Support.v4" Version="28.0.0.3" />
|
||||
<PackageReference Include="Xamarin.Android.Support.v7.RecyclerView" Version="28.0.0.3" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
|
|
|
@ -269,21 +269,21 @@
|
|||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Xamarin.Android.Support.Animated.Vector.Drawable" Version="28.0.0.1" />
|
||||
<PackageReference Include="Xamarin.Android.Support.Annotations" Version="28.0.0.1" />
|
||||
<PackageReference Include="Xamarin.Android.Support.Compat" Version="28.0.0.1" />
|
||||
<PackageReference Include="Xamarin.Android.Support.Core.UI" Version="28.0.0.1" />
|
||||
<PackageReference Include="Xamarin.Android.Support.Core.Utils" Version="28.0.0.1" />
|
||||
<PackageReference Include="Xamarin.Android.Support.CustomTabs" Version="28.0.0.1" />
|
||||
<PackageReference Include="Xamarin.Android.Support.Design" Version="28.0.0.1" />
|
||||
<PackageReference Include="Xamarin.Android.Support.Fragment" Version="28.0.0.1" />
|
||||
<PackageReference Include="Xamarin.Android.Support.Transition" Version="28.0.0.1" />
|
||||
<PackageReference Include="Xamarin.Android.Support.v4" Version="28.0.0.1" />
|
||||
<PackageReference Include="Xamarin.Android.Support.v7.AppCompat" Version="28.0.0.1" />
|
||||
<PackageReference Include="Xamarin.Android.Support.v7.CardView" Version="28.0.0.1" />
|
||||
<PackageReference Include="Xamarin.Android.Support.v7.Palette" Version="28.0.0.1" />
|
||||
<PackageReference Include="Xamarin.Android.Support.v7.RecyclerView" Version="28.0.0.1" />
|
||||
<PackageReference Include="Xamarin.Android.Support.Vector.Drawable" Version="28.0.0.1" />
|
||||
<PackageReference Include="Xamarin.Android.Support.Animated.Vector.Drawable" Version="28.0.0.3" />
|
||||
<PackageReference Include="Xamarin.Android.Support.Annotations" Version="28.0.0.3" />
|
||||
<PackageReference Include="Xamarin.Android.Support.Compat" Version="28.0.0.3" />
|
||||
<PackageReference Include="Xamarin.Android.Support.Core.UI" Version="28.0.0.3" />
|
||||
<PackageReference Include="Xamarin.Android.Support.Core.Utils" Version="28.0.0.3" />
|
||||
<PackageReference Include="Xamarin.Android.Support.CustomTabs" Version="28.0.0.3" />
|
||||
<PackageReference Include="Xamarin.Android.Support.Design" Version="28.0.0.3" />
|
||||
<PackageReference Include="Xamarin.Android.Support.Fragment" Version="28.0.0.3" />
|
||||
<PackageReference Include="Xamarin.Android.Support.Transition" Version="28.0.0.3" />
|
||||
<PackageReference Include="Xamarin.Android.Support.v4" Version="28.0.0.3" />
|
||||
<PackageReference Include="Xamarin.Android.Support.v7.AppCompat" Version="28.0.0.3" />
|
||||
<PackageReference Include="Xamarin.Android.Support.v7.CardView" Version="28.0.0.3" />
|
||||
<PackageReference Include="Xamarin.Android.Support.v7.Palette" Version="28.0.0.3" />
|
||||
<PackageReference Include="Xamarin.Android.Support.v7.RecyclerView" Version="28.0.0.3" />
|
||||
<PackageReference Include="Xamarin.Android.Support.Vector.Drawable" Version="28.0.0.3" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
|
||||
</Project>
|
||||
|
|
|
@ -69,8 +69,8 @@
|
|||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Xamarin.Android.Support.v4" Version="28.0.0.1" />
|
||||
<PackageReference Include="Xamarin.Android.Support.v7.RecyclerView" Version="28.0.0.1" />
|
||||
<PackageReference Include="Xamarin.Android.Support.v4" Version="28.0.0.3" />
|
||||
<PackageReference Include="Xamarin.Android.Support.v7.RecyclerView" Version="28.0.0.3" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
|
||||
</Project>
|
|
@ -33,7 +33,12 @@ namespace Xamarin.Forms.Build.Tasks
|
|||
|
||||
internal string Type { get; set; }
|
||||
internal MethodDefinition InitCompForType { get; private set; }
|
||||
internal bool ReadOnly { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Enable to optimize for shorter build time
|
||||
/// e.g. OptimizeIL unused, Debug symbols not loaded, no assemblies written
|
||||
/// </summary>
|
||||
public bool ValidateOnly { get; set; }
|
||||
|
||||
public override bool Execute(out IList<Exception> thrownExceptions)
|
||||
{
|
||||
|
@ -72,8 +77,8 @@ namespace Xamarin.Forms.Build.Tasks
|
|||
|
||||
var readerParameters = new ReaderParameters {
|
||||
AssemblyResolver = resolver,
|
||||
ReadWrite = !ReadOnly,
|
||||
ReadSymbols = debug,
|
||||
ReadWrite = !ValidateOnly,
|
||||
ReadSymbols = debug && !ValidateOnly, // We don't need symbols for ValidateOnly, since we won't be writing
|
||||
};
|
||||
|
||||
using (var assemblyDefinition = AssemblyDefinition.ReadAssembly(Path.GetFullPath(Assembly),readerParameters)) {
|
||||
|
@ -147,24 +152,29 @@ namespace Xamarin.Forms.Build.Tasks
|
|||
(string)xamlFilePathAttr.ConstructorArguments[0].Value :
|
||||
resource.Name;
|
||||
|
||||
var initCompRuntime = typeDef.Methods.FirstOrDefault(md => md.Name == "__InitComponentRuntime");
|
||||
if (initCompRuntime != null)
|
||||
LoggingHelper.LogMessage(Low, $"{new string(' ', 6)}__InitComponentRuntime already exists... not creating");
|
||||
else {
|
||||
LoggingHelper.LogMessage(Low, $"{new string(' ', 6)}Creating empty {typeDef.Name}.__InitComponentRuntime");
|
||||
initCompRuntime = new MethodDefinition("__InitComponentRuntime", initComp.Attributes, initComp.ReturnType);
|
||||
initCompRuntime.Body.InitLocals = true;
|
||||
LoggingHelper.LogMessage(Low, $"{new string(' ', 8)}done.");
|
||||
LoggingHelper.LogMessage(Low, $"{new string(' ', 6)}Copying body of InitializeComponent to __InitComponentRuntime");
|
||||
initCompRuntime.Body = new MethodBody(initCompRuntime);
|
||||
var iCRIl = initCompRuntime.Body.GetILProcessor();
|
||||
foreach (var instr in initComp.Body.Instructions)
|
||||
iCRIl.Append(instr);
|
||||
initComp.Body.Instructions.Clear();
|
||||
initComp.Body.GetILProcessor().Emit(OpCodes.Ret);
|
||||
initComp.Body.InitLocals = true;
|
||||
typeDef.Methods.Add(initCompRuntime);
|
||||
LoggingHelper.LogMessage(Low, $"{new string(' ', 8)}done.");
|
||||
MethodDefinition initCompRuntime = null;
|
||||
if (!ValidateOnly)
|
||||
{
|
||||
initCompRuntime = typeDef.Methods.FirstOrDefault(md => md.Name == "__InitComponentRuntime");
|
||||
if (initCompRuntime != null)
|
||||
LoggingHelper.LogMessage(Low, $"{new string(' ', 6)}__InitComponentRuntime already exists... not creating");
|
||||
else
|
||||
{
|
||||
LoggingHelper.LogMessage(Low, $"{new string(' ', 6)}Creating empty {typeDef.Name}.__InitComponentRuntime");
|
||||
initCompRuntime = new MethodDefinition("__InitComponentRuntime", initComp.Attributes, initComp.ReturnType);
|
||||
initCompRuntime.Body.InitLocals = true;
|
||||
LoggingHelper.LogMessage(Low, $"{new string(' ', 8)}done.");
|
||||
LoggingHelper.LogMessage(Low, $"{new string(' ', 6)}Copying body of InitializeComponent to __InitComponentRuntime");
|
||||
initCompRuntime.Body = new MethodBody(initCompRuntime);
|
||||
var iCRIl = initCompRuntime.Body.GetILProcessor();
|
||||
foreach (var instr in initComp.Body.Instructions)
|
||||
iCRIl.Append(instr);
|
||||
initComp.Body.Instructions.Clear();
|
||||
initComp.Body.GetILProcessor().Emit(OpCodes.Ret);
|
||||
initComp.Body.InitLocals = true;
|
||||
typeDef.Methods.Add(initCompRuntime);
|
||||
LoggingHelper.LogMessage(Low, $"{new string(' ', 8)}done.");
|
||||
}
|
||||
}
|
||||
|
||||
LoggingHelper.LogMessage(Low, $"{new string(' ', 6)}Parsing Xaml");
|
||||
|
@ -197,6 +207,9 @@ namespace Xamarin.Forms.Build.Tasks
|
|||
|
||||
LoggingHelper.LogMessage(Low, $"{new string(' ', 8)}done.");
|
||||
|
||||
if (ValidateOnly)
|
||||
continue;
|
||||
|
||||
if (OptimizeIL) {
|
||||
LoggingHelper.LogMessage(Low, $"{new string(' ', 6)}Optimizing IL");
|
||||
initComp.Body.Optimize();
|
||||
|
@ -224,14 +237,14 @@ namespace Xamarin.Forms.Build.Tasks
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ValidateOnly) {
|
||||
LoggingHelper.LogMessage(Low, $"{new string(' ', 0)}ValidateOnly=True. Skipping writing assembly.");
|
||||
return success;
|
||||
}
|
||||
if (!hasCompiledXamlResources) {
|
||||
LoggingHelper.LogMessage(Low, $"{new string(' ', 0)}No compiled resources. Skipping writing assembly.");
|
||||
return success;
|
||||
}
|
||||
|
||||
if (ReadOnly)
|
||||
return success;
|
||||
|
||||
LoggingHelper.LogMessage(Low, $"{new string(' ', 0)}Writing the assembly");
|
||||
try {
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
using System;
|
||||
using Android.Content;
|
||||
using Android.OS;
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.ControlGallery.Android;
|
||||
using Xamarin.Forms.Controls;
|
||||
using Xamarin.Forms.Platform.Android;
|
||||
|
||||
[assembly: ExportRenderer(typeof(ApiLabel), typeof(ApiLabelRenderer))]
|
||||
namespace Xamarin.Forms.ControlGallery.Android
|
||||
{
|
||||
public class ApiLabelRenderer : Xamarin.Forms.Platform.Android.FastRenderers.LabelRenderer
|
||||
{
|
||||
public ApiLabelRenderer(Context context) : base(context)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
|
||||
{
|
||||
Element.Text = ((int)Build.VERSION.SdkInt).ToString();
|
||||
base.OnElementChanged(e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -112,6 +112,7 @@
|
|||
<Compile Include="..\Xamarin.Forms.Controls\GalleryPages\OpenGLGalleries\AdvancedOpenGLGallery.cs">
|
||||
<Link>GalleryPages\AdvancedOpenGLGallery.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="ApiLabelRenderer.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidAsset Include="Assets\default.css" />
|
||||
|
@ -341,21 +342,21 @@
|
|||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Xamarin.Android.Support.Animated.Vector.Drawable" Version="28.0.0.1" />
|
||||
<PackageReference Include="Xamarin.Android.Support.Annotations" Version="28.0.0.1" />
|
||||
<PackageReference Include="Xamarin.Android.Support.Compat" Version="28.0.0.1" />
|
||||
<PackageReference Include="Xamarin.Android.Support.Core.UI" Version="28.0.0.1" />
|
||||
<PackageReference Include="Xamarin.Android.Support.Core.Utils" Version="28.0.0.1" />
|
||||
<PackageReference Include="Xamarin.Android.Support.CustomTabs" Version="28.0.0.1" />
|
||||
<PackageReference Include="Xamarin.Android.Support.Design" Version="28.0.0.1" />
|
||||
<PackageReference Include="Xamarin.Android.Support.Fragment" Version="28.0.0.1" />
|
||||
<PackageReference Include="Xamarin.Android.Support.Transition" Version="28.0.0.1" />
|
||||
<PackageReference Include="Xamarin.Android.Support.v4" Version="28.0.0.1" />
|
||||
<PackageReference Include="Xamarin.Android.Support.v7.AppCompat" Version="28.0.0.1" />
|
||||
<PackageReference Include="Xamarin.Android.Support.v7.CardView" Version="28.0.0.1" />
|
||||
<PackageReference Include="Xamarin.Android.Support.v7.Palette" Version="28.0.0.1" />
|
||||
<PackageReference Include="Xamarin.Android.Support.v7.RecyclerView" Version="28.0.0.1" />
|
||||
<PackageReference Include="Xamarin.Android.Support.Vector.Drawable" Version="28.0.0.1" />
|
||||
<PackageReference Include="Xamarin.Android.Support.Animated.Vector.Drawable" Version="28.0.0.3" />
|
||||
<PackageReference Include="Xamarin.Android.Support.Annotations" Version="28.0.0.3" />
|
||||
<PackageReference Include="Xamarin.Android.Support.Compat" Version="28.0.0.3" />
|
||||
<PackageReference Include="Xamarin.Android.Support.Core.UI" Version="28.0.0.3" />
|
||||
<PackageReference Include="Xamarin.Android.Support.Core.Utils" Version="28.0.0.3" />
|
||||
<PackageReference Include="Xamarin.Android.Support.CustomTabs" Version="28.0.0.3" />
|
||||
<PackageReference Include="Xamarin.Android.Support.Design" Version="28.0.0.3" />
|
||||
<PackageReference Include="Xamarin.Android.Support.Fragment" Version="28.0.0.3" />
|
||||
<PackageReference Include="Xamarin.Android.Support.Transition" Version="28.0.0.3" />
|
||||
<PackageReference Include="Xamarin.Android.Support.v4" Version="28.0.0.3" />
|
||||
<PackageReference Include="Xamarin.Android.Support.v7.AppCompat" Version="28.0.0.3" />
|
||||
<PackageReference Include="Xamarin.Android.Support.v7.CardView" Version="28.0.0.3" />
|
||||
<PackageReference Include="Xamarin.Android.Support.v7.Palette" Version="28.0.0.3" />
|
||||
<PackageReference Include="Xamarin.Android.Support.v7.RecyclerView" Version="28.0.0.3" />
|
||||
<PackageReference Include="Xamarin.Android.Support.Vector.Drawable" Version="28.0.0.3" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidAsset Include="Assets\fonts\ionicons.ttf">
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
using System;
|
||||
using UIKit;
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.ControlGallery.iOS;
|
||||
using Xamarin.Forms.Controls;
|
||||
using Xamarin.Forms.Platform.iOS;
|
||||
|
||||
[assembly: ExportRenderer(typeof(ApiLabel), typeof(ApiLabelRenderer))]
|
||||
namespace Xamarin.Forms.ControlGallery.iOS
|
||||
{
|
||||
public class ApiLabelRenderer : LabelRenderer
|
||||
{
|
||||
|
||||
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
|
||||
{
|
||||
Element.Text = UIDevice.CurrentDevice.SystemVersion.ToString();
|
||||
base.OnElementChanged(e);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -126,6 +126,7 @@
|
|||
<Compile Include="CustomEffects\GradientEffect.cs" />
|
||||
<Compile Include="CustomRenderers\CustomRenderer.cs" />
|
||||
<Compile Include="CustomRenderers\RoundedLabelRenderer.cs" />
|
||||
<Compile Include="ApiLabelRenderer.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Xamarin.Forms.Controls\Xamarin.Forms.Controls.csproj">
|
||||
|
|
|
@ -74,6 +74,12 @@ namespace Xamarin.Forms.Controls.Issues
|
|||
RunningApp.Tap (q => q.Marked ("btnDismissModal"));
|
||||
RunningApp.Tap (q => q.Marked ("btnMaster"));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Wait for the test to finish loading before exiting otherwise
|
||||
// the next UI test might start running while this is still loading
|
||||
RunningApp.WaitForElement(q => q.Marked("btnModal"));
|
||||
}
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
|
|
|
@ -45,7 +45,7 @@ namespace Xamarin.Forms.Controls.Issues
|
|||
#if UITEST && __IOS__
|
||||
[Test]
|
||||
[Category(UITestCategories.ManualReview)]
|
||||
[Ignore]
|
||||
[Ignore("Fails sometimes")]
|
||||
public void Bugzilla35736Test()
|
||||
{
|
||||
RunningApp.WaitForElement(q => q.Marked("Bugzilla35736Editor"));
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
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.None, 0, "CollectionView ItemsSource Types", PlatformAffected.All)]
|
||||
public class CollectionViewItemsSourceTypes : TestContentPage
|
||||
{
|
||||
protected override void Init()
|
||||
{
|
||||
#if APP
|
||||
FlagTestHelpers.SetCollectionViewTestFlag();
|
||||
#endif
|
||||
Content = new StackLayout()
|
||||
{
|
||||
Children =
|
||||
{
|
||||
new Label()
|
||||
{
|
||||
Text = "If you see three 900s this test has passed"
|
||||
},
|
||||
new CollectionView()
|
||||
{
|
||||
ItemsSource = new[] { 900 },
|
||||
HeightRequest = 50
|
||||
},
|
||||
new CollectionView()
|
||||
{
|
||||
ItemsSource = new[] { "900" }.ToList<object>(),
|
||||
HeightRequest = 50
|
||||
},
|
||||
new CollectionView()
|
||||
{
|
||||
ItemsSource = new ObservableCollection<string>(new[] { "900" }),
|
||||
HeightRequest = 50
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#if UITEST
|
||||
[Test]
|
||||
public void CollectionViewItemsSourceTypesDisplayAndDontCrash()
|
||||
{
|
||||
RunningApp.QueryUntilPresent(() =>
|
||||
{
|
||||
var result = RunningApp.WaitForElement("900");
|
||||
|
||||
if (result.Length == 3)
|
||||
return result;
|
||||
|
||||
return null;
|
||||
});
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
using System;
|
||||
namespace Xamarin.Forms.Controls
|
||||
{
|
||||
public class ApiLabel : Label
|
||||
{
|
||||
public ApiLabel()
|
||||
{
|
||||
AutomationId = "ApiLabel";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,356 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Xamarin.Forms.CustomAttributes;
|
||||
using Xamarin.Forms.Internals;
|
||||
using Xamarin.Forms.PlatformConfiguration;
|
||||
using Xamarin.Forms.PlatformConfiguration.iOSSpecific;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#if UITEST
|
||||
using Xamarin.Forms.Core.UITests;
|
||||
using Xamarin.UITest;
|
||||
using NUnit.Framework;
|
||||
#endif
|
||||
|
||||
namespace Xamarin.Forms.Controls.Issues
|
||||
{
|
||||
#if UITEST
|
||||
[NUnit.Framework.Category(UITestCategories.CollectionView)]
|
||||
#endif
|
||||
[Preserve(AllMembers = true)]
|
||||
[Issue(IssueTracker.Github, 6889, "Labels disappearing in CollectionView", PlatformAffected.Android)]
|
||||
public class Issue6889 : TestNavigationPage
|
||||
{
|
||||
protected override void Init()
|
||||
{
|
||||
#if APP
|
||||
Device.SetFlags(new List<string>(Device.Flags ?? new List<string>()) { "CollectionView_Experimental" });
|
||||
|
||||
PushAsync(CreateRoot());
|
||||
#endif
|
||||
}
|
||||
|
||||
public ContentPage CreateRoot()
|
||||
{
|
||||
var page = new ContentPage { Title = "Issue6889" };
|
||||
|
||||
var layout = new StackLayout();
|
||||
|
||||
var instructions = new Label { Text = "Scroll the CollectionView below up and down quickly several times."
|
||||
+ " If any rows of labels disappear, this test has failed" };
|
||||
|
||||
layout.Children.Add(instructions);
|
||||
|
||||
var cv = new CollectionView();
|
||||
|
||||
var template = new DataTemplate(() => {
|
||||
var grid = new Grid
|
||||
{
|
||||
ColumnDefinitions = new ColumnDefinitionCollection
|
||||
{
|
||||
new ColumnDefinition { Width = GridLength.Auto },
|
||||
new ColumnDefinition { Width = GridLength.Auto }
|
||||
}
|
||||
};
|
||||
|
||||
var label1 = new Label { HorizontalOptions = LayoutOptions.Start };
|
||||
label1.SetBinding(Label.TextProperty, new Binding("Text1"));
|
||||
grid.Children.Add(label1);
|
||||
Grid.SetColumn(label1, 0);
|
||||
|
||||
var label2 = new Label { HorizontalOptions = LayoutOptions.StartAndExpand };
|
||||
label2.SetBinding(Label.TextProperty, new Binding("Text2"));
|
||||
grid.Children.Add(label2);
|
||||
Grid.SetColumn(label2, 1);
|
||||
|
||||
return grid;
|
||||
});
|
||||
|
||||
cv.ItemTemplate = template;
|
||||
cv.SetBinding(ItemsView.ItemsSourceProperty, new Binding("SampleList"));
|
||||
|
||||
layout.Children.Add(cv);
|
||||
|
||||
page.Content = layout;
|
||||
|
||||
page.BindingContext = new _6889MainViewModel();
|
||||
|
||||
return page;
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve(AllMembers = true)]
|
||||
public class _6889TextModel
|
||||
{
|
||||
public string Text1 { get; set; }
|
||||
public string Text2 { get; set; }
|
||||
}
|
||||
|
||||
[Preserve(AllMembers = true)]
|
||||
public class _6889MainViewModel
|
||||
{
|
||||
public _6889MainViewModel()
|
||||
{
|
||||
SampleList = new ObservableCollection<_6889TextModel>
|
||||
{
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
new _6889TextModel { Text1="Text1",Text2="Text2"},
|
||||
};
|
||||
}
|
||||
|
||||
public ObservableCollection<_6889TextModel> SampleList { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,146 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Xamarin.Forms.CustomAttributes;
|
||||
using Xamarin.Forms.Internals;
|
||||
using System.ComponentModel;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
#if UITEST
|
||||
using Xamarin.Forms.Core.UITests;
|
||||
using Xamarin.UITest;
|
||||
using NUnit.Framework;
|
||||
#endif
|
||||
|
||||
namespace Xamarin.Forms.Controls.Issues
|
||||
{
|
||||
#if UITEST
|
||||
[NUnit.Framework.Category(UITestCategories.CollectionView)]
|
||||
#endif
|
||||
[Preserve(AllMembers = true)]
|
||||
[Issue(IssueTracker.Github, 7128, "[iOS] Changing model property scrolls CollectionView back to top",
|
||||
PlatformAffected.iOS)]
|
||||
public class Issue7128 : TestNavigationPage
|
||||
{
|
||||
protected override void Init()
|
||||
{
|
||||
FlagTestHelpers.SetCollectionViewTestFlag();
|
||||
PushAsync(CreateRoot());
|
||||
}
|
||||
|
||||
class _7128Model : INotifyPropertyChanged
|
||||
{
|
||||
private string _url;
|
||||
private string _text;
|
||||
|
||||
public _7128Model(string url, string text)
|
||||
{
|
||||
Url = url;
|
||||
Text = text;
|
||||
}
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
public string Url
|
||||
{
|
||||
get => _url;
|
||||
set
|
||||
{
|
||||
_url = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public string Text
|
||||
{
|
||||
get => _text;
|
||||
set
|
||||
{
|
||||
_text = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null)
|
||||
{
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
}
|
||||
|
||||
View Template()
|
||||
{
|
||||
var layout = new Grid();
|
||||
|
||||
layout.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
|
||||
layout.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
|
||||
|
||||
var image = new Image { Aspect = Aspect.AspectFill };
|
||||
image.SetBinding(Image.SourceProperty, new Binding("Url"));
|
||||
|
||||
var label = new Label { Margin = 10, BackgroundColor = Color.Red, HorizontalOptions = LayoutOptions.Fill };
|
||||
label.SetBinding(Label.TextProperty, new Binding("Text"));
|
||||
|
||||
layout.Children.Add(image);
|
||||
layout.Children.Add(label);
|
||||
Grid.SetRow(image, 0);
|
||||
Grid.SetRow(image, 1);
|
||||
|
||||
var tapGesture = new TapGestureRecognizer();
|
||||
tapGesture.Tapped += Tapped;
|
||||
|
||||
label.GestureRecognizers.Add(tapGesture);
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
void Tapped(object sender, EventArgs e)
|
||||
{
|
||||
var label = sender as Label;
|
||||
|
||||
var model = (_7128Model)label.BindingContext;
|
||||
|
||||
model.Text = DateTime.UtcNow.Millisecond.ToString();
|
||||
}
|
||||
|
||||
Page CreateRoot()
|
||||
{
|
||||
var page = new ContentPage() { Title = "Issue7128" };
|
||||
|
||||
var layout = new StackLayout() { Padding = 5 };
|
||||
|
||||
var instructions = new Label { Text = "Scroll the CollectionView down several pages, then click on one " +
|
||||
"of the labels. The text of the label should change, but the CollectionView should not scroll to a " +
|
||||
"different location. If it does scroll, the test has failed."
|
||||
};
|
||||
|
||||
layout.Children.Add(instructions);
|
||||
|
||||
var cv = new CollectionView
|
||||
{
|
||||
ItemTemplate = new DataTemplate(() => Template())
|
||||
};
|
||||
|
||||
var source = new ObservableCollection<_7128Model>();
|
||||
|
||||
var images = new string[] {
|
||||
"https://raw.githubusercontent.com/xamarin/Xamarin.Forms/master/Xamarin.Forms.ControlGallery.iOS/oasis.jpg",
|
||||
"https://raw.githubusercontent.com/xamarin/Xamarin.Forms/master/Xamarin.Forms.ControlGallery.iOS/photo.jpg",
|
||||
"https://raw.githubusercontent.com/xamarin/Xamarin.Forms/master/Xamarin.Forms.ControlGallery.iOS/xamarinstore.jpg",
|
||||
"https://raw.githubusercontent.com/xamarin/Xamarin.Forms/master/Xamarin.Forms.ControlGallery.iOS/crimson.jpg",
|
||||
"https://raw.githubusercontent.com/xamarin/Xamarin.Forms/master/Xamarin.Forms.ControlGallery.WindowsUniversal/cover1.jpg"
|
||||
};
|
||||
|
||||
for (int n = 0; n < 35; n++)
|
||||
{
|
||||
source.Add(new _7128Model(images[n % 5], $"{n}.jpg"));
|
||||
}
|
||||
|
||||
cv.ItemsSource = source;
|
||||
|
||||
layout.Children.Add(cv);
|
||||
|
||||
page.Content = layout;
|
||||
|
||||
return page;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Text;
|
||||
using Xamarin.Forms.CustomAttributes;
|
||||
using Xamarin.Forms.Internals;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
||||
#if UITEST
|
||||
using Xamarin.UITest;
|
||||
using NUnit.Framework;
|
||||
using Xamarin.Forms.Core.UITests;
|
||||
#endif
|
||||
|
||||
namespace Xamarin.Forms.Controls.Issues
|
||||
{
|
||||
[Preserve(AllMembers = true)]
|
||||
[Issue(IssueTracker.Github, 7329, "[Android] ListView scroll not working when inside a ScrollView",
|
||||
PlatformAffected.Android)]
|
||||
#if UITEST
|
||||
[NUnit.Framework.Category(UITestCategories.ListView)]
|
||||
[NUnit.Framework.Category(UITestCategories.ScrollView)]
|
||||
#endif
|
||||
public class Issue7329 : TestContentPage
|
||||
{
|
||||
ListView listView = null;
|
||||
protected override void Init()
|
||||
{
|
||||
listView = new ListView() { AutomationId = "NestedListView" };
|
||||
listView.ItemsSource = Enumerable.Range(0, 200).Select(x=> new Data() { Text = x }).ToList();
|
||||
|
||||
Content = new ScrollView()
|
||||
{
|
||||
AutomationId = "ParentScrollView",
|
||||
Content = new StackLayout()
|
||||
{
|
||||
Children =
|
||||
{
|
||||
new ApiLabel(),
|
||||
new Label() { Text = "If the List View can scroll the test has passed"},
|
||||
listView
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
[Preserve(AllMembers = true)]
|
||||
public class Data
|
||||
{
|
||||
public int Text { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Text.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
#if UITEST
|
||||
[Test]
|
||||
public void ScrollListViewInsideScrollView()
|
||||
{
|
||||
|
||||
#if __ANDROID__
|
||||
if (!RunningApp.IsApiHigherThan(21))
|
||||
return;
|
||||
#endif
|
||||
|
||||
RunningApp.WaitForElement("1");
|
||||
RunningApp.ScrollDownTo("30", strategy: ScrollStrategy.Gesture);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
using Xamarin.Forms.CustomAttributes;
|
||||
using Xamarin.Forms.Internals;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#if UITEST
|
||||
using Xamarin.Forms.Core.UITests;
|
||||
using Xamarin.UITest;
|
||||
using NUnit.Framework;
|
||||
#endif
|
||||
|
||||
namespace Xamarin.Forms.Controls.Issues
|
||||
{
|
||||
#if UITEST
|
||||
[Category(UITestCategories.ListView)]
|
||||
#endif
|
||||
[Preserve(AllMembers = true)]
|
||||
[Issue(IssueTracker.Github, 7371, "iOS race condition(or not checking for null) of refreshing(offset animation) causes NullReferenceException", PlatformAffected.iOS)]
|
||||
public class Issue7371 : TestContentPage
|
||||
{
|
||||
ListView ListView => Content as ListView;
|
||||
protected override void Init()
|
||||
{
|
||||
Content = new ListView();
|
||||
}
|
||||
|
||||
protected override void OnAppearing()
|
||||
{
|
||||
base.OnAppearing();
|
||||
|
||||
ListView.IsRefreshing = true;
|
||||
|
||||
Application.Current.MainPage = new ContentPage() { Content = new Label { Text = "Success", VerticalOptions = LayoutOptions.Center } };
|
||||
|
||||
ListView.IsRefreshing = false;
|
||||
}
|
||||
|
||||
#if UITEST
|
||||
[Test]
|
||||
public async Task RefreshingListViewCrashesWhenDisposedTest()
|
||||
{
|
||||
await Task.Delay(500);
|
||||
RunningApp.WaitForElement(q => q.Marked("Success"));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -240,9 +240,7 @@ namespace Xamarin.Forms.Controls
|
|||
|
||||
public void SwipeRight()
|
||||
{
|
||||
#pragma warning disable 618
|
||||
_app.SwipeRight();
|
||||
#pragma warning restore 618
|
||||
SwipeLeftToRight();
|
||||
}
|
||||
|
||||
public void SwipeLeftToRight(double swipePercentage = 0.67, int swipeSpeed = 500, bool withInertia = true)
|
||||
|
@ -257,9 +255,7 @@ namespace Xamarin.Forms.Controls
|
|||
|
||||
public void SwipeLeft()
|
||||
{
|
||||
#pragma warning disable 618
|
||||
_app.SwipeLeft();
|
||||
#pragma warning restore 618
|
||||
SwipeRightToLeft();
|
||||
}
|
||||
|
||||
public void SwipeRightToLeft(double swipePercentage = 0.67, int swipeSpeed = 500, bool withInertia = true)
|
||||
|
|
|
@ -783,7 +783,7 @@ namespace Xamarin.Forms.Controls.Issues
|
|||
[SetUpFixture]
|
||||
public class IssuesSetup
|
||||
{
|
||||
[SetUp]
|
||||
[OneTimeSetUp]
|
||||
public void RunBeforeAnyTests()
|
||||
{
|
||||
AppSetup.RunningApp = AppSetup.Setup(null);
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
<Import_RootNamespace>Xamarin.Forms.Controls.Issues</Import_RootNamespace>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="$(MSBuildThisFileDirectory)CollectionViewItemsSourceTypes.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Issue1455.xaml.cs">
|
||||
<DependentUpon>Issue1455.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
|
@ -18,7 +19,9 @@
|
|||
<Compile Include="$(MSBuildThisFileDirectory)CollectionViewHeaderFooterView.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)CollectionViewItemsUpdatingScrollMode.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Issue3475.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Issue6889.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Issue6945.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Issue7329.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Issue7290.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Issue7240.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Issue5046.xaml.cs">
|
||||
|
@ -38,6 +41,7 @@
|
|||
<Compile Include="$(MSBuildThisFileDirectory)ScrollToGroup.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)NestedCollectionViews.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)ShellFlyoutBehavior.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Issue7128.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)ShellGestures.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)ShellBackButtonBehavior.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Issue7102.cs" />
|
||||
|
@ -568,6 +572,7 @@
|
|||
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla39853.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)MultipleClipToBounds.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Issue6994.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Issue7371.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)_TemplateMarkup.xaml.cs">
|
||||
<DependentUpon>_TemplateMarkup.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
|
@ -1042,6 +1047,7 @@
|
|||
<Compile Include="$(MSBuildThisFileDirectory)Issue7053.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Issue6894.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Issue6929.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Controls\ApiLabel.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Bugzilla22229.xaml">
|
||||
|
@ -1374,4 +1380,4 @@
|
|||
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
|
@ -46,12 +46,12 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
||||
<PackageReference Include="NUnit" Version="2.6.4" />
|
||||
<PackageReference Include="NUnitTestAdapter">
|
||||
<Version>2.2.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="NUnit" Version="3.12.0" />
|
||||
<PackageReference Include="Xam.Plugin.DeviceInfo" Version="3.0.2" />
|
||||
<PackageReference Include="Xamarin.UITest" Version="2.2.7" />
|
||||
<PackageReference Include="Xamarin.UITest" Version="3.0.3" />
|
||||
<PackageReference Include="NUnit3TestAdapter">
|
||||
<Version>3.15.1</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="BaseViewContainerRemoteAndroid.cs" />
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace Xamarin.Forms.Core.UITests
|
|||
|
||||
public static AppRect ScreenBounds { get; set; }
|
||||
|
||||
[TestFixtureTearDown]
|
||||
[OneTimeTearDown]
|
||||
protected virtual void FixtureTeardown()
|
||||
{
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ namespace Xamarin.Forms.Core.UITests
|
|||
[SetUp]
|
||||
protected virtual void TestSetup()
|
||||
{
|
||||
EnsureMemory();
|
||||
//EnsureMemory();
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
|
@ -55,9 +55,7 @@ namespace Xamarin.Forms.Core.UITests
|
|||
|
||||
protected abstract void NavigateToGallery();
|
||||
|
||||
#pragma warning disable 618
|
||||
[TestFixtureSetUp]
|
||||
#pragma warning restore 618
|
||||
[OneTimeSetUp]
|
||||
protected virtual void FixtureSetup()
|
||||
{
|
||||
ResetApp();
|
||||
|
@ -111,7 +109,6 @@ namespace Xamarin.Forms.Core.UITests
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if UITEST
|
||||
|
||||
namespace Xamarin.Forms.Core.UITests
|
||||
|
@ -121,7 +118,7 @@ namespace Xamarin.Forms.Core.UITests
|
|||
[SetUpFixture]
|
||||
public class CoreUITestsSetup
|
||||
{
|
||||
[SetUp]
|
||||
[OneTimeSetUp]
|
||||
public void RunBeforeAnyTests()
|
||||
{
|
||||
LaunchApp();
|
||||
|
@ -138,4 +135,4 @@ namespace Xamarin.Forms.Core.UITests
|
|||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -5,6 +5,7 @@ using Xamarin.UITest;
|
|||
using Xamarin.UITest.Queries;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using Xamarin.Forms.Controls.Issues;
|
||||
#if __IOS__
|
||||
using Xamarin.UITest.iOS;
|
||||
#endif
|
||||
|
@ -32,6 +33,16 @@ namespace Xamarin.UITest
|
|||
return results;
|
||||
}
|
||||
|
||||
public static bool IsApiHigherThan(this IApp app, int apiLevel, string apiLabelId = "ApiLevel")
|
||||
{
|
||||
var api = Convert.ToInt32(app.WaitForElement("ApiLabel")[0].ReadText());
|
||||
|
||||
if (api < apiLevel)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#if __IOS__
|
||||
public static void SendAppToBackground(this IApp app, TimeSpan timeSpan)
|
||||
{
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace Xamarin.Forms.Core.UnitTests
|
|||
{
|
||||
[Test]
|
||||
//https://bugzilla.xamarin.com/show_bug.cgi?id=51424
|
||||
public async void AnimationRepeats()
|
||||
public async Task AnimationRepeats()
|
||||
{
|
||||
var box = new BoxView();
|
||||
Assume.That(box.Rotation, Is.EqualTo(0d));
|
||||
|
|
|
@ -1588,7 +1588,7 @@ namespace Xamarin.Forms.Core.UnitTests
|
|||
Assert.That (() => bindable.SetBinding (MockBindable.TextProperty, new Binding ("Text2")), Throws.Nothing);
|
||||
Assert.That (bindable.Text, Is.EqualTo (MockBindable.TextProperty.DefaultValue));
|
||||
Assert.That (log.Messages.Count, Is.EqualTo (1), "An error was not logged");
|
||||
Assert.That (log.Messages[0], Is.StringContaining (String.Format (BindingExpression.PropertyNotFoundErrorMessage,
|
||||
Assert.That (log.Messages[0], Does.Contain(String.Format (BindingExpression.PropertyNotFoundErrorMessage,
|
||||
"Text2",
|
||||
"Xamarin.Forms.Core.UnitTests.BindingUnitTests+DifferentViewModel",
|
||||
"Xamarin.Forms.Core.UnitTests.MockBindable",
|
||||
|
@ -1607,7 +1607,7 @@ namespace Xamarin.Forms.Core.UnitTests
|
|||
Assert.That (bindable.Text, Is.EqualTo ("Foo"));
|
||||
|
||||
Assert.That (log.Messages.Count, Is.Not.GreaterThan (1), "Too many errors were logged");
|
||||
Assert.That (log.Messages[0], Is.StringContaining (String.Format (BindingExpression.PropertyNotFoundErrorMessage,
|
||||
Assert.That (log.Messages[0], Does.Contain(String.Format (BindingExpression.PropertyNotFoundErrorMessage,
|
||||
"Text",
|
||||
"Xamarin.Forms.Core.UnitTests.BindingUnitTests+EmptyViewModel",
|
||||
"Xamarin.Forms.Core.UnitTests.MockBindable",
|
||||
|
@ -1621,7 +1621,7 @@ namespace Xamarin.Forms.Core.UnitTests
|
|||
Assert.That (() => bindable.SetBinding (MockBindable.TextProperty, new Binding ("Text")), Throws.Nothing);
|
||||
|
||||
Assert.That (log.Messages.Count, Is.EqualTo (1), "An error was not logged");
|
||||
Assert.That (log.Messages[0], Is.StringContaining (String.Format (BindingExpression.PropertyNotFoundErrorMessage,
|
||||
Assert.That (log.Messages[0], Does.Contain(String.Format (BindingExpression.PropertyNotFoundErrorMessage,
|
||||
"Text",
|
||||
"Xamarin.Forms.Core.UnitTests.BindingUnitTests+DifferentViewModel",
|
||||
"Xamarin.Forms.Core.UnitTests.MockBindable",
|
||||
|
@ -1637,7 +1637,7 @@ namespace Xamarin.Forms.Core.UnitTests
|
|||
Assert.That (() => bindable.SetBinding (MockBindable.TextProperty, new Binding ("PrivateSetter")), Throws.Nothing);
|
||||
|
||||
Assert.That (log.Messages.Count, Is.EqualTo (1), "An error was not logged");
|
||||
Assert.That (log.Messages[0], Is.StringContaining (String.Format (BindingExpression.PropertyNotFoundErrorMessage,
|
||||
Assert.That (log.Messages[0], Does.Contain(String.Format (BindingExpression.PropertyNotFoundErrorMessage,
|
||||
"PrivateSetter",
|
||||
"Xamarin.Forms.Core.UnitTests.BindingUnitTests+DifferentViewModel",
|
||||
"Xamarin.Forms.Core.UnitTests.MockBindable",
|
||||
|
@ -1646,7 +1646,7 @@ namespace Xamarin.Forms.Core.UnitTests
|
|||
Assert.That (() => bindable.SetValueCore (MockBindable.TextProperty, "foo"), Throws.Nothing);
|
||||
|
||||
Assert.That (log.Messages.Count, Is.EqualTo (2), "An error was not logged");
|
||||
Assert.That (log.Messages[1], Is.StringContaining (String.Format (BindingExpression.PropertyNotFoundErrorMessage,
|
||||
Assert.That (log.Messages[1], Does.Contain(String.Format (BindingExpression.PropertyNotFoundErrorMessage,
|
||||
"PrivateSetter",
|
||||
"Xamarin.Forms.Core.UnitTests.BindingUnitTests+DifferentViewModel",
|
||||
"Xamarin.Forms.Core.UnitTests.MockBindable",
|
||||
|
@ -1660,7 +1660,7 @@ namespace Xamarin.Forms.Core.UnitTests
|
|||
Assert.That (() => bindable.SetBinding (MockBindable.TextProperty, new Binding ("MissingProperty")), Throws.Nothing);
|
||||
|
||||
Assert.That (log.Messages.Count, Is.EqualTo (1), "An error was not logged");
|
||||
Assert.That (log.Messages[0], Is.StringContaining (String.Format (BindingExpression.PropertyNotFoundErrorMessage,
|
||||
Assert.That (log.Messages[0], Does.Contain(String.Format (BindingExpression.PropertyNotFoundErrorMessage,
|
||||
"MissingProperty",
|
||||
"Xamarin.Forms.Core.UnitTests.MockViewModel",
|
||||
"Xamarin.Forms.Core.UnitTests.MockBindable",
|
||||
|
@ -1688,7 +1688,7 @@ namespace Xamarin.Forms.Core.UnitTests
|
|||
Assert.That (() => bindable.SetBinding (MockBindable.TextProperty, new Binding ("Model.MissingProperty")), Throws.Nothing);
|
||||
|
||||
Assert.That (log.Messages.Count, Is.EqualTo (1), "An error was not logged");
|
||||
Assert.That (log.Messages[0], Is.StringContaining (String.Format (BindingExpression.PropertyNotFoundErrorMessage,
|
||||
Assert.That (log.Messages[0], Does.Contain(String.Format (BindingExpression.PropertyNotFoundErrorMessage,
|
||||
"MissingProperty",
|
||||
"Xamarin.Forms.Core.UnitTests.BindingBaseUnitTests+ComplexMockViewModel",
|
||||
"Xamarin.Forms.Core.UnitTests.MockBindable",
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Xamarin.Forms.Core.UnitTests
|
||||
{
|
||||
|
@ -153,7 +154,7 @@ namespace Xamarin.Forms.Core.UnitTests
|
|||
}
|
||||
|
||||
[Test]
|
||||
public async void ForceUpdateSizeCallsAreRateLimited()
|
||||
public async Task ForceUpdateSizeCallsAreRateLimited()
|
||||
{
|
||||
var lv = new ListView { HasUnevenRows = true };
|
||||
var cell = new ViewCell { Parent = lv };
|
||||
|
@ -172,7 +173,7 @@ namespace Xamarin.Forms.Core.UnitTests
|
|||
}
|
||||
|
||||
[Test]
|
||||
public async void ForceUpdateSizeWillNotBeCalledIfParentIsNotAListViewWithUnevenRows ()
|
||||
public async Task ForceUpdateSizeWillNotBeCalledIfParentIsNotAListViewWithUnevenRows ()
|
||||
{
|
||||
var lv = new ListView { HasUnevenRows = false };
|
||||
var cell = new ViewCell { Parent = lv };
|
||||
|
|
|
@ -11,7 +11,7 @@ namespace Xamarin.Forms.Core.UnitTests
|
|||
public class GeocoderUnitTests : BaseTestFixture
|
||||
{
|
||||
[Test]
|
||||
public async void AddressesForPosition ()
|
||||
public async Task AddressesForPosition ()
|
||||
{
|
||||
Geocoder.GetAddressesForPositionFuncAsync = GetAddressesForPositionFuncAsync;
|
||||
var geocoder = new Geocoder ();
|
||||
|
@ -26,7 +26,7 @@ namespace Xamarin.Forms.Core.UnitTests
|
|||
}
|
||||
|
||||
[Test]
|
||||
public async void PositionsForAddress () {
|
||||
public async Task PositionsForAddress () {
|
||||
Geocoder.GetPositionsForAddressAsyncFunc = GetPositionsForAddressAsyncFunc ;
|
||||
var geocoder = new Geocoder ();
|
||||
var result = await geocoder.GetPositionsForAddressAsync ("quux");
|
||||
|
|
|
@ -61,14 +61,14 @@ namespace Xamarin.Forms.Core.UnitTests
|
|||
[TestFixture]
|
||||
public class MotionTests : BaseTestFixture
|
||||
{
|
||||
[TestFixtureSetUp]
|
||||
[OneTimeSetUp]
|
||||
public void Init ()
|
||||
{
|
||||
Device.PlatformServices = new MockPlatformServices ();
|
||||
Ticker.Default = new BlockingTicker ();
|
||||
}
|
||||
|
||||
[TestFixtureTearDown]
|
||||
[OneTimeTearDown]
|
||||
public void End ()
|
||||
{
|
||||
Device.PlatformServices = null;
|
||||
|
@ -154,14 +154,14 @@ namespace Xamarin.Forms.Core.UnitTests
|
|||
[TestFixture]
|
||||
public class TickerSystemEnabledTests
|
||||
{
|
||||
[TestFixtureSetUp]
|
||||
[OneTimeSetUp]
|
||||
public void Init ()
|
||||
{
|
||||
Device.PlatformServices = new MockPlatformServices ();
|
||||
Ticker.Default = new AsyncTicker();
|
||||
}
|
||||
|
||||
[TestFixtureTearDown]
|
||||
[OneTimeTearDown]
|
||||
public void End ()
|
||||
{
|
||||
Device.PlatformServices = null;
|
||||
|
|
|
@ -441,7 +441,7 @@ namespace Xamarin.Forms.Core.UnitTests
|
|||
}
|
||||
|
||||
[Test]
|
||||
public async void HandlesPopToRoot ()
|
||||
public async Task HandlesPopToRoot ()
|
||||
{
|
||||
var root = new ContentPage { Title = "Root" };
|
||||
var navPage = new NavigationPage (root);
|
||||
|
@ -489,7 +489,7 @@ namespace Xamarin.Forms.Core.UnitTests
|
|||
}
|
||||
|
||||
[Test]
|
||||
public async void NavigatesBackWhenBackButtonPressed ()
|
||||
public async Task NavigatesBackWhenBackButtonPressed ()
|
||||
{
|
||||
var root = new ContentPage { Title = "Root" };
|
||||
var navPage = new NavigationPage (root);
|
||||
|
@ -503,7 +503,7 @@ namespace Xamarin.Forms.Core.UnitTests
|
|||
}
|
||||
|
||||
[Test]
|
||||
public async void DoesNotNavigatesBackWhenBackButtonPressedIfHandled ()
|
||||
public async Task DoesNotNavigatesBackWhenBackButtonPressedIfHandled ()
|
||||
{
|
||||
var root = new BackButtonPage { Title = "Root" };
|
||||
var second = new BackButtonPage () {Handle = true};
|
||||
|
@ -562,7 +562,7 @@ namespace Xamarin.Forms.Core.UnitTests
|
|||
}
|
||||
|
||||
[Test]
|
||||
public async void TestRemovePage()
|
||||
public async Task TestRemovePage()
|
||||
{
|
||||
var root = new ContentPage { Title = "Root" };
|
||||
var newPage = new ContentPage();
|
||||
|
|
|
@ -261,7 +261,7 @@ namespace Xamarin.Forms.Core.UnitTests
|
|||
var rd = new ResourceDictionary();
|
||||
rd.Add("foo", "bar");
|
||||
var ex = Assert.Throws<KeyNotFoundException>(() => { var foo = rd ["test_invalid_key"]; });
|
||||
Assert.That(ex.Message, Is.StringContaining("test_invalid_key"));
|
||||
Assert.That(ex.Message, Does.Contain("test_invalid_key"));
|
||||
}
|
||||
|
||||
class MyRD : ResourceDictionary
|
||||
|
|
|
@ -342,6 +342,37 @@ namespace Xamarin.Forms.Core.UnitTests
|
|||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void AppearingOnlyForVisiblePage()
|
||||
{
|
||||
Shell shell = new Shell();
|
||||
var pageAppearing = new ContentPage();
|
||||
var pageNotAppearing = new ContentPage();
|
||||
|
||||
FlyoutItem flyoutItem = new FlyoutItem();
|
||||
Tab tab = new Tab();
|
||||
ShellContent content = new ShellContent() { Content = pageAppearing };
|
||||
|
||||
bool pageAppearingFired = false;
|
||||
bool pageNotAppearingFired = false;
|
||||
|
||||
pageAppearing.Appearing += (_, __) => pageAppearingFired = true;
|
||||
pageNotAppearing.Appearing += (_, __) =>
|
||||
{
|
||||
pageNotAppearingFired = true;
|
||||
};
|
||||
|
||||
shell.Items.Add(flyoutItem);
|
||||
flyoutItem.Items.Add(tab);
|
||||
tab.Items.Add(content);
|
||||
|
||||
var notAppearingContent = new ShellContent();
|
||||
tab.Items.Add(notAppearingContent);
|
||||
notAppearingContent.Content = pageNotAppearing;
|
||||
|
||||
Assert.True(pageAppearingFired, "Correct Page Appearing Fired");
|
||||
Assert.False(pageNotAppearingFired, "Incorrect Page Appearing Fired");
|
||||
}
|
||||
|
||||
|
||||
class ShellLifeCycleState
|
||||
|
|
|
@ -668,7 +668,7 @@ namespace Xamarin.Forms.Core.UnitTests
|
|||
Assert.AreEqual(bindingContext, menuItem2.BindingContext);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Test]
|
||||
public async Task TitleViewLogicalChild()
|
||||
{
|
||||
Shell shell = new Shell();
|
||||
|
@ -709,9 +709,37 @@ namespace Xamarin.Forms.Core.UnitTests
|
|||
shell.FlyoutHeader = null;
|
||||
|
||||
Assert.False(shell.ChildrenNotDrawnByThisElement.Contains(layout));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public async Task ShellFlyoutBehaviorCalculation()
|
||||
{
|
||||
Shell shell = new Shell();
|
||||
ContentPage page = new ContentPage();
|
||||
shell.Items.Add(CreateShellItem(page: page));
|
||||
Assert.AreEqual(FlyoutBehavior.Flyout, shell.GetEffectiveFlyoutBehavior());
|
||||
|
||||
Shell.SetFlyoutBehavior(page, FlyoutBehavior.Disabled);
|
||||
Shell.SetFlyoutBehavior(shell.Items[0].Items[0].Items[0], FlyoutBehavior.Flyout);
|
||||
Shell.SetFlyoutBehavior(shell.Items[0].Items[0], FlyoutBehavior.Disabled);
|
||||
Shell.SetFlyoutBehavior(shell.Items[0], FlyoutBehavior.Locked);
|
||||
|
||||
Assert.AreEqual(FlyoutBehavior.Disabled, shell.GetEffectiveFlyoutBehavior());
|
||||
|
||||
page.ClearValue(Shell.FlyoutBehaviorProperty);
|
||||
Assert.AreEqual(FlyoutBehavior.Flyout, shell.GetEffectiveFlyoutBehavior());
|
||||
|
||||
shell.Items[0].Items[0].Items[0].ClearValue(Shell.FlyoutBehaviorProperty);
|
||||
Assert.AreEqual(FlyoutBehavior.Disabled, shell.GetEffectiveFlyoutBehavior());
|
||||
|
||||
shell.Items[0].Items[0].ClearValue(Shell.FlyoutBehaviorProperty);
|
||||
Assert.AreEqual(FlyoutBehavior.Locked, shell.GetEffectiveFlyoutBehavior());
|
||||
|
||||
shell.Items[0].ClearValue(Shell.FlyoutBehaviorProperty);
|
||||
Assert.AreEqual(FlyoutBehavior.Flyout, shell.GetEffectiveFlyoutBehavior());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TabBarAutoCreation()
|
||||
{
|
||||
|
|
|
@ -1,23 +1,45 @@
|
|||
using NUnit.Framework;
|
||||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Xamarin.Forms.Internals;
|
||||
|
||||
namespace Xamarin.Forms.Core.UnitTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class StyleTests : BaseTestFixture
|
||||
{
|
||||
internal class Logger : LogListener
|
||||
{
|
||||
public IReadOnlyList<string> Messages {
|
||||
get { return messages; }
|
||||
}
|
||||
|
||||
public override void Warning(string category, string message)
|
||||
{
|
||||
messages.Add("[" + category + "] " + message);
|
||||
}
|
||||
|
||||
readonly List<string> messages = new List<string>();
|
||||
}
|
||||
|
||||
internal Logger log;
|
||||
|
||||
[SetUp]
|
||||
public override void Setup ()
|
||||
{
|
||||
base.Setup ();
|
||||
log = new Logger();
|
||||
Device.PlatformServices = new MockPlatformServices ();
|
||||
Log.Listeners.Add(log);
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
Log.Listeners.Remove(log);
|
||||
Application.Current = null;
|
||||
}
|
||||
|
||||
|
@ -411,7 +433,7 @@ namespace Xamarin.Forms.Core.UnitTests
|
|||
|
||||
[Test]
|
||||
//https://bugzilla.xamarin.com/show_bug.cgi?id=31207
|
||||
public async void StyleDontHoldStrongReferences ()
|
||||
public async Task StyleDontHoldStrongReferences ()
|
||||
{
|
||||
var style = new Style (typeof(Label));
|
||||
var label = new Label ();
|
||||
|
@ -828,27 +850,39 @@ namespace Xamarin.Forms.Core.UnitTests
|
|||
}
|
||||
|
||||
[Test]
|
||||
public void MismatchTargetTypeThrowsError1()
|
||||
public void MismatchTargetTypeLogsWarningMessage1()
|
||||
{
|
||||
var s = new Style(typeof(Button));
|
||||
var t = new View();
|
||||
Assert.Throws<ArgumentException>(() => t.Style = s);
|
||||
|
||||
t.Style = s;
|
||||
|
||||
Assert.AreEqual(log.Messages.Count, 1);
|
||||
Assert.AreEqual(log.Messages.FirstOrDefault(), $"[Styles] Style TargetType Xamarin.Forms.Button is not compatible with element target type Xamarin.Forms.View");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MismatchTargetTypeThrowsError2()
|
||||
public void MismatchTargetTypeLogsWarningMessage2()
|
||||
{
|
||||
var s = new Style(typeof(Button));
|
||||
var t = new Label();
|
||||
Assert.Throws<ArgumentException>(() => t.Style = s);
|
||||
|
||||
t.Style = s;
|
||||
|
||||
Assert.AreEqual(log.Messages.Count, 1);
|
||||
Assert.AreEqual(log.Messages.FirstOrDefault(), $"[Styles] Style TargetType Xamarin.Forms.Button is not compatible with element target type Xamarin.Forms.Label");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MatchTargetTypeDoesntThrowError()
|
||||
public void MatchTargetTypeDoesntLogWarningMessage()
|
||||
{
|
||||
var s = new Style(typeof(View));
|
||||
var t = new Button();
|
||||
Assert.DoesNotThrow(() => t.Style = s);
|
||||
|
||||
t.Style = s;
|
||||
|
||||
Assert.That(log.Messages.Count, Is.EqualTo(0),
|
||||
"A warning was logged: " + log.Messages.FirstOrDefault());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1490,7 +1490,7 @@ namespace Xamarin.Forms.Core.UnitTests
|
|||
}
|
||||
|
||||
[Test]
|
||||
[Ignore]
|
||||
[Ignore("SpeedTestApply")]
|
||||
public void SpeedTestApply()
|
||||
{
|
||||
|
||||
|
@ -1560,7 +1560,7 @@ namespace Xamarin.Forms.Core.UnitTests
|
|||
}
|
||||
|
||||
[Test]
|
||||
[Ignore]
|
||||
[Ignore("SpeedTestSetBC")]
|
||||
public void SpeedTestSetBC()
|
||||
{
|
||||
var property = BindableProperty.Create("Foo", typeof(string), typeof(MockBindable));
|
||||
|
|
|
@ -48,7 +48,7 @@ namespace Xamarin.Forms.Core.UnitTests
|
|||
}
|
||||
|
||||
[Test]
|
||||
[Ignore]
|
||||
[Ignore("LoadImageFromStream")]
|
||||
public void LoadImageFromStream ()
|
||||
{
|
||||
var loader = new UriImageSource {
|
||||
|
@ -60,7 +60,7 @@ namespace Xamarin.Forms.Core.UnitTests
|
|||
}
|
||||
|
||||
[Test]
|
||||
[Ignore]
|
||||
[Ignore("SecondCallLoadFromCache")]
|
||||
public void SecondCallLoadFromCache ()
|
||||
{
|
||||
var loader = new UriImageSource {
|
||||
|
@ -80,7 +80,7 @@ namespace Xamarin.Forms.Core.UnitTests
|
|||
}
|
||||
|
||||
[Test]
|
||||
[Ignore]
|
||||
[Ignore("DoNotKeepFailedRetrieveInCache")]
|
||||
public void DoNotKeepFailedRetrieveInCache ()
|
||||
{
|
||||
var loader = new UriImageSource {
|
||||
|
@ -98,7 +98,7 @@ namespace Xamarin.Forms.Core.UnitTests
|
|||
}
|
||||
|
||||
[Test]
|
||||
[Ignore]
|
||||
[Ignore("ConcurrentCallsOnSameUriAreQueued")]
|
||||
public void ConcurrentCallsOnSameUriAreQueued ()
|
||||
{
|
||||
var loader = new UriImageSource {
|
||||
|
|
|
@ -45,8 +45,10 @@
|
|||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="NUnit" Version="2.6.4" />
|
||||
<PackageReference Include="NUnitTestAdapter" Version="2.2.0" />
|
||||
<PackageReference Include="NUnit" Version="3.12.0" />
|
||||
<PackageReference Include="NUnit3TestAdapter">
|
||||
<Version>3.15.1</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
|
||||
|
@ -246,8 +248,9 @@
|
|||
</ItemGroup>
|
||||
<Target Name="_CopyNUnitTestAdapterFiles" AfterTargets="Build">
|
||||
<ItemGroup>
|
||||
<_NUnitTestAdapterFiles Include="$(NuGetPackageRoot)NUnitTestAdapter\%(Version)\**" Condition="@(PackageReference -> '%(Identity)') == 'NUnitTestAdapter'" InProject="False" />
|
||||
<_NUnitTestAdapterFiles Include="$(NuGetPackageRoot)NUnit3TestAdapter\%(Version)\build\net35\**" Condition="@(PackageReference -> '%(Identity)') == 'NUnit3TestAdapter'" InProject="False" />
|
||||
</ItemGroup>
|
||||
<Copy SourceFiles="@(_NUnitTestAdapterFiles)" DestinationFolder="$(SolutionDir)packages\NUnitTestAdapter.AnyVersion\%(RecursiveDir)" ContinueOnError="true" Retries="0" />
|
||||
<Copy SourceFiles="@(_NUnitTestAdapterFiles)" DestinationFolder="$(SolutionDir)packages\NUnitTestAdapter.AnyVersion\tools\%(RecursiveDir)" ContinueOnError="true" Retries="0" />
|
||||
<Copy SourceFiles="@(_NUnitTestAdapterFiles)" DestinationFolder="$(SolutionDir)packages\NUnitTestAdapter.AnyVersion\build\%(RecursiveDir)" ContinueOnError="true" Retries="0" />
|
||||
</Target>
|
||||
</Project>
|
|
@ -49,14 +49,14 @@
|
|||
<PackageReference Include="Castle.Core" Version="4.3.1" />
|
||||
<PackageReference Include="DotNetSeleniumExtras.PageObjects" Version="3.11.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
||||
<PackageReference Include="NUnit" Version="2.6.4" />
|
||||
<PackageReference Include="NUnitTestAdapter">
|
||||
<Version>2.2.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="NUnit" Version="3.12.0" />
|
||||
<PackageReference Include="Selenium.Support" Version="3.14.0" />
|
||||
<PackageReference Include="Selenium.WebDriver" Version="3.14.0" />
|
||||
<PackageReference Include="Xam.Plugin.DeviceInfo" Version="3.0.2" />
|
||||
<PackageReference Include="Xamarin.UITest" Version="2.2.7" />
|
||||
<PackageReference Include="Xamarin.UITest" Version="3.0.3" />
|
||||
<PackageReference Include="NUnit3TestAdapter">
|
||||
<Version>3.15.1</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="WindowsTestBase.cs" />
|
||||
|
|
|
@ -46,9 +46,9 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
||||
<PackageReference Include="NUnit" Version="2.6.4" />
|
||||
<PackageReference Include="NUnit" Version="3.12.0" />
|
||||
<PackageReference Include="Xam.Plugin.DeviceInfo" Version="3.0.2" />
|
||||
<PackageReference Include="Xamarin.UITest" Version="2.2.7" />
|
||||
<PackageReference Include="Xamarin.UITest" Version="3.0.3" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="BaseViewContainerRemoteiOS.cs" />
|
||||
|
|
|
@ -48,12 +48,12 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
||||
<PackageReference Include="NUnit" Version="2.6.4" />
|
||||
<PackageReference Include="NUnit" Version="3.12.0" />
|
||||
<PackageReference Include="ServiceStack.Client" Version="4.5.12" />
|
||||
<PackageReference Include="ServiceStack.Interfaces" Version="4.5.12" />
|
||||
<PackageReference Include="ServiceStack.Text" Version="4.5.12" />
|
||||
<PackageReference Include="Xam.Plugin.DeviceInfo" Version="3.0.2" />
|
||||
<PackageReference Include="Xamarin.UITest" Version="2.2.7" />
|
||||
<PackageReference Include="Xamarin.UITest" Version="3.0.3" />
|
||||
<PackageReference Include="Xamarin.UITest.Desktop" Version="0.0.7" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@ -89,4 +89,4 @@
|
|||
</ItemGroup>
|
||||
<Copy SourceFiles="@(_XamarinUITestFiles)" DestinationFolder="$(SolutionDir)packages\Xamarin.UITest.AnyVersion\%(RecursiveDir)" ContinueOnError="true" Retries="0" />
|
||||
</Target>
|
||||
</Project>
|
||||
</Project>
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Windows.Input;
|
||||
using Xamarin.Forms.Platform;
|
||||
|
||||
|
@ -216,11 +217,13 @@ namespace Xamarin.Forms
|
|||
return 0;
|
||||
}
|
||||
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public void SetCurrentItem(object item)
|
||||
{
|
||||
SetValueFromRenderer(CurrentItemProperty, item);
|
||||
}
|
||||
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public void SetIsDragging(bool value)
|
||||
{
|
||||
SetValue(IsDraggingPropertyKey, value);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
@ -40,7 +40,7 @@ namespace Xamarin.Forms
|
|||
if (_style == value)
|
||||
return;
|
||||
if (value != null && !value.TargetType.IsAssignableFrom(TargetType))
|
||||
throw new ArgumentException($"Style TargetType {value.TargetType.FullName} is not compatible with element target type {TargetType}");
|
||||
Log.Warning("Styles", $"Style TargetType {value.TargetType.FullName} is not compatible with element target type {TargetType}");
|
||||
SetStyle(ImplicitStyle, ClassStyles, value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -954,17 +954,21 @@ namespace Xamarin.Forms
|
|||
return lookupDict;
|
||||
}
|
||||
|
||||
FlyoutBehavior GetEffectiveFlyoutBehavior()
|
||||
{
|
||||
var page = WalkToPage(this);
|
||||
internal FlyoutBehavior GetEffectiveFlyoutBehavior() => GetEffectiveValue(Shell.FlyoutBehaviorProperty, FlyoutBehavior);
|
||||
|
||||
while (page != this && page != null)
|
||||
T GetEffectiveValue<T>(BindableProperty property, T defaultValue)
|
||||
{
|
||||
Element element = GetVisiblePage();
|
||||
|
||||
while (element != this && element != null)
|
||||
{
|
||||
if (page.IsSet(FlyoutBehaviorProperty))
|
||||
return GetFlyoutBehavior(page);
|
||||
page = page.Parent;
|
||||
if (element.IsSet(property))
|
||||
return (T)element.GetValue(property);
|
||||
|
||||
element = element.Parent;
|
||||
}
|
||||
return FlyoutBehavior;
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
ShellAppearance GetAppearanceForPivot(Element pivot)
|
||||
|
@ -988,7 +992,7 @@ namespace Xamarin.Forms
|
|||
|
||||
// One minor deviation here. Even though a pushed page is technically the child of
|
||||
// a ShellSection and not the ShellContent, we want the root ShellContent to
|
||||
// be taken into account. Yes this could behavior oddly if the developer switches
|
||||
// be taken into account. Yes this could behave oddly if the developer switches
|
||||
// tabs while a page is pushed, however that is in the developers wheelhouse
|
||||
// and this will be the generally expected behavior.
|
||||
if (!foundShellContent && pivot is ShellSection shellSection && shellSection.CurrentItem != null)
|
||||
|
@ -1060,6 +1064,14 @@ namespace Xamarin.Forms
|
|||
return !navArgs.Cancelled;
|
||||
}
|
||||
|
||||
internal Element GetVisiblePage()
|
||||
{
|
||||
if (CurrentItem?.CurrentItem is IShellSectionController scc)
|
||||
return scc.PresentedPage;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
Element WalkToPage(Element element)
|
||||
{
|
||||
switch (element)
|
||||
|
|
|
@ -86,7 +86,7 @@ namespace Xamarin.Forms
|
|||
|
||||
public ShellContent() => ((INotifyCollectionChanged)MenuItems).CollectionChanged += MenuItemsCollectionChanged;
|
||||
|
||||
internal bool IsVisibleContent => Parent is ShellSection shellSection && shellSection.IsVisibleSection;
|
||||
internal bool IsVisibleContent => Parent is ShellSection shellSection && shellSection.IsVisibleSection && shellSection.CurrentItem == this;
|
||||
internal override ReadOnlyCollection<Element> LogicalChildrenInternal => _logicalChildrenReadOnly ?? (_logicalChildrenReadOnly = new ReadOnlyCollection<Element>(_logicalChildren));
|
||||
|
||||
internal override void SendDisappearing()
|
||||
|
|
|
@ -78,7 +78,7 @@
|
|||
<PackageReference Include="Xamarin.GooglePlayServices.Maps" Version="60.1142.1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Xamarin.Android.Support.v4" Version="28.0.0.1" />
|
||||
<PackageReference Include="Xamarin.Android.Support.v4" Version="28.0.0.3" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
|
||||
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
|
||||
|
|
|
@ -69,8 +69,8 @@
|
|||
<Compile Include="MaterialCheckBoxRenderer.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Xamarin.Android.Support.v7.AppCompat" Version="28.0.0.1" />
|
||||
<PackageReference Include="Xamarin.Android.Support.Design" Version="28.0.0.1" />
|
||||
<PackageReference Include="Xamarin.Android.Support.v7.AppCompat" Version="28.0.0.3" />
|
||||
<PackageReference Include="Xamarin.Android.Support.Design" Version="28.0.0.3" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\values-v21\styles.xml">
|
||||
|
|
|
@ -42,8 +42,10 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
||||
<PackageReference Include="NUnit" Version="2.6.4" />
|
||||
<PackageReference Include="NUnitTestAdapter" Version="2.2.0" />
|
||||
<PackageReference Include="NUnit" Version="3.12.0" />
|
||||
<PackageReference Include="NUnit3TestAdapter">
|
||||
<Version>3.15.1</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\Xamarin.Forms.Core.UnitTests\MockDispatcherProvider.cs">
|
||||
|
@ -83,8 +85,9 @@
|
|||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Target Name="_CopyNUnitTestAdapterFiles" AfterTargets="Build">
|
||||
<ItemGroup>
|
||||
<_NUnitTestAdapterFiles Include="$(NuGetPackageRoot)NUnitTestAdapter\%(Version)\**" Condition="@(PackageReference -> '%(Identity)') == 'NUnitTestAdapter'" InProject="False" />
|
||||
<_NUnitTestAdapterFiles Include="$(NuGetPackageRoot)NUnit3TestAdapter\%(Version)\build\net35\**" Condition="@(PackageReference -> '%(Identity)') == 'NUnit3TestAdapter'" InProject="False" />
|
||||
</ItemGroup>
|
||||
<Copy SourceFiles="@(_NUnitTestAdapterFiles)" DestinationFolder="$(SolutionDir)packages\NUnitTestAdapter.AnyVersion\%(RecursiveDir)" ContinueOnError="true" Retries="0" />
|
||||
<Copy SourceFiles="@(_NUnitTestAdapterFiles)" DestinationFolder="$(SolutionDir)packages\NUnitTestAdapter.AnyVersion\tools\%(RecursiveDir)" ContinueOnError="true" Retries="0" />
|
||||
<Copy SourceFiles="@(_NUnitTestAdapterFiles)" DestinationFolder="$(SolutionDir)packages\NUnitTestAdapter.AnyVersion\build\%(RecursiveDir)" ContinueOnError="true" Retries="0" />
|
||||
</Target>
|
||||
</Project>
|
|
@ -66,7 +66,7 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Xamarin.GooglePlayServices.AppIndexing" Version="60.1142.1" />
|
||||
<PackageReference Include="Xamarin.Android.Support.v4" Version="28.0.0.1" />
|
||||
<PackageReference Include="Xamarin.Android.Support.v4" Version="28.0.0.3" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectToBuild Include="Xamarin.Forms.Platform.Android.AppLinks.csproj">
|
||||
|
|
|
@ -19,6 +19,7 @@ namespace Xamarin.Forms.Platform.Android
|
|||
|
||||
public ListSource(IEnumerable enumerable)
|
||||
{
|
||||
_itemsSource = new List<object>();
|
||||
foreach (object item in enumerable)
|
||||
{
|
||||
_itemsSource.Add(item);
|
||||
|
|
|
@ -34,7 +34,6 @@ namespace Xamarin.Forms.Platform.Android
|
|||
|
||||
public void Recycle(ItemsView itemsView)
|
||||
{
|
||||
View.BindingContext = null;
|
||||
itemsView.RemoveLogicalChild(View);
|
||||
}
|
||||
|
||||
|
@ -51,7 +50,7 @@ namespace Xamarin.Forms.Platform.Android
|
|||
_selectedTemplate = template;
|
||||
}
|
||||
|
||||
_itemContentView.HandleItemSizingStrategy(reportMeasure, size);
|
||||
_itemContentView.HandleItemSizingStrategy(reportMeasure, size);
|
||||
|
||||
// Set the binding context before we add it as a child of the ItemsView; otherwise, it will
|
||||
// inherit the ItemsView's binding context
|
||||
|
|
|
@ -666,15 +666,18 @@ namespace Xamarin.Forms
|
|||
|
||||
public async Task<Stream> GetStreamAsync(Uri uri, CancellationToken cancellationToken)
|
||||
{
|
||||
using (var client = new HttpClient())
|
||||
using (HttpResponseMessage response = await client.GetAsync(uri, cancellationToken))
|
||||
using (var client = new HttpClient())
|
||||
{
|
||||
HttpResponseMessage response = await client.GetAsync(uri, cancellationToken).ConfigureAwait(false);
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
Internals.Log.Warning("HTTP Request", $"Could not retrieve {uri}, status code {response.StatusCode}");
|
||||
return null;
|
||||
}
|
||||
return await response.Content.ReadAsStreamAsync();
|
||||
|
||||
// the HttpResponseMessage needs to be disposed of after the calling code is done with the stream
|
||||
// otherwise the stream may get disposed before the caller can use it
|
||||
return new StreamWrapper(await response.Content.ReadAsStreamAsync().ConfigureAwait(false), response);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Xamarin.Forms
|
||||
{
|
||||
internal class StreamWrapper : Stream
|
||||
{
|
||||
Stream _wrapped;
|
||||
IDisposable _additionalDisposable;
|
||||
|
||||
public StreamWrapper(Stream wrapped, IDisposable additionalDisposable)
|
||||
{
|
||||
if (wrapped == null)
|
||||
throw new ArgumentNullException("wrapped");
|
||||
|
||||
_wrapped = wrapped;
|
||||
_additionalDisposable = additionalDisposable;
|
||||
}
|
||||
|
||||
public override bool CanRead
|
||||
{
|
||||
get { return _wrapped.CanRead; }
|
||||
}
|
||||
|
||||
public override bool CanSeek
|
||||
{
|
||||
get { return _wrapped.CanSeek; }
|
||||
}
|
||||
|
||||
public override bool CanWrite
|
||||
{
|
||||
get { return _wrapped.CanWrite; }
|
||||
}
|
||||
|
||||
public override long Length
|
||||
{
|
||||
get { return _wrapped.Length; }
|
||||
}
|
||||
|
||||
public override long Position
|
||||
{
|
||||
get { return _wrapped.Position; }
|
||||
set { _wrapped.Position = value; }
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
_wrapped.Flush();
|
||||
}
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
return _wrapped.Read(buffer, offset, count);
|
||||
}
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
return _wrapped.Seek(offset, origin);
|
||||
}
|
||||
|
||||
public override void SetLength(long value)
|
||||
{
|
||||
_wrapped.SetLength(value);
|
||||
}
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
_wrapped.Write(buffer, offset, count);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
_wrapped.Dispose();
|
||||
|
||||
_additionalDisposable?.Dispose();
|
||||
_additionalDisposable = null;
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -116,8 +116,7 @@ namespace Xamarin.Forms.Platform.Android
|
|||
internal static T GetParentOfType<T>(this IViewParent view)
|
||||
where T : class
|
||||
{
|
||||
T t = view as T;
|
||||
if (view != null)
|
||||
if (view is T t)
|
||||
return t;
|
||||
|
||||
while (view != null)
|
||||
|
@ -142,4 +141,4 @@ namespace Xamarin.Forms.Platform.Android
|
|||
return view.Parent.GetParentOfType<T>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -255,6 +255,7 @@
|
|||
<Compile Include="Renderers\ViewCellExtensions.cs" />
|
||||
<Compile Include="Renderers\ViewGroupExtensions.cs" />
|
||||
<AndroidResource Include="Resources\Layout\RootLayout.axml" />
|
||||
<Compile Include="StreamWrapper.cs" />
|
||||
<Compile Include="TapGestureHandler.cs" />
|
||||
<Compile Include="TextColorSwitcher.cs" />
|
||||
<Compile Include="ViewInitializedEventArgs.cs" />
|
||||
|
@ -353,9 +354,9 @@
|
|||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Xamarin.Android.Support.Design" Version="28.0.0.1" />
|
||||
<PackageReference Include="Xamarin.Android.Support.v4" Version="28.0.0.1" />
|
||||
<PackageReference Include="Xamarin.Android.Support.v7.CardView" Version="28.0.0.1" />
|
||||
<PackageReference Include="Xamarin.Android.Support.Design" Version="28.0.0.3" />
|
||||
<PackageReference Include="Xamarin.Android.Support.v4" Version="28.0.0.3" />
|
||||
<PackageReference Include="Xamarin.Android.Support.v7.CardView" Version="28.0.0.3" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\Layout\ShellContent.axml" />
|
||||
|
|
|
@ -104,12 +104,17 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
}
|
||||
|
||||
var itemTemplate = Element.ItemTemplate;
|
||||
|
||||
if (_collectionViewSource != null)
|
||||
{
|
||||
if (_collectionViewSource.Source is ObservableItemTemplateCollection observableItemTemplateCollection)
|
||||
{
|
||||
observableItemTemplateCollection.CleanUp();
|
||||
}
|
||||
}
|
||||
|
||||
if (itemTemplate != null)
|
||||
{
|
||||
// The ItemContentControls need the actual data item and the template so they can inflate the template
|
||||
// and bind the result to the data item.
|
||||
// ItemTemplateEnumerator handles pairing them up for the ItemContentControls to consume
|
||||
|
||||
_collectionViewSource = new CollectionViewSource
|
||||
{
|
||||
Source = TemplatedItemSourceFactory.Create(itemsSource, itemTemplate, Element),
|
||||
|
@ -135,33 +140,9 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
return;
|
||||
}
|
||||
|
||||
var formsTemplate = Element.ItemTemplate;
|
||||
var itemsControlItemTemplate = ListViewBase.ItemTemplate;
|
||||
ListViewBase.ItemTemplate = Element.ItemTemplate == null ? null : ItemsViewTemplate;
|
||||
|
||||
if (formsTemplate == null)
|
||||
{
|
||||
ListViewBase.ItemTemplate = null;
|
||||
|
||||
if (itemsControlItemTemplate != null)
|
||||
{
|
||||
// We've removed the template; the itemssource should be updated
|
||||
// TODO hartez 2018/06/25 21:25:24 I don't love that changing the template might reset the whole itemssource. We should think about a way to make that unnecessary
|
||||
UpdateItemsSource();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO hartez 2018/06/23 13:47:27 Handle DataTemplateSelector case
|
||||
// Actually, DataTemplateExtensions CreateContent might handle the selector for us
|
||||
|
||||
ListViewBase.ItemTemplate = ItemsViewTemplate;
|
||||
|
||||
if (itemsControlItemTemplate == null)
|
||||
{
|
||||
// We're using a data template now, so we'll need to update the itemsource
|
||||
UpdateItemsSource();
|
||||
}
|
||||
UpdateItemsSource();
|
||||
}
|
||||
|
||||
protected virtual void UpdateHeader()
|
||||
|
|
|
@ -7,9 +7,10 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
{
|
||||
internal class ObservableItemTemplateCollection : ObservableCollection<ItemTemplateContext>
|
||||
{
|
||||
readonly IList _innerSource;
|
||||
readonly IList _itemsSource;
|
||||
readonly DataTemplate _itemTemplate;
|
||||
readonly BindableObject _container;
|
||||
readonly INotifyCollectionChanged _notifyCollectionChanged;
|
||||
|
||||
public ObservableItemTemplateCollection(IList itemsSource, DataTemplate itemTemplate, BindableObject container)
|
||||
{
|
||||
|
@ -18,7 +19,9 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
throw new ArgumentException($"{nameof(itemsSource)} must implement {nameof(INotifyCollectionChanged)}");
|
||||
}
|
||||
|
||||
_innerSource = itemsSource;
|
||||
_notifyCollectionChanged = notifyCollectionChanged;
|
||||
|
||||
_itemsSource = itemsSource;
|
||||
_itemTemplate = itemTemplate;
|
||||
_container = container;
|
||||
for (int n = 0; n < itemsSource.Count; n++)
|
||||
|
@ -26,25 +29,32 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
Add(new ItemTemplateContext (itemTemplate, itemsSource[n], container));
|
||||
}
|
||||
|
||||
notifyCollectionChanged.CollectionChanged += InnerCollectionChanged;
|
||||
_notifyCollectionChanged.CollectionChanged += InnerCollectionChanged;
|
||||
}
|
||||
|
||||
public void CleanUp()
|
||||
{
|
||||
_notifyCollectionChanged.CollectionChanged -= InnerCollectionChanged;
|
||||
}
|
||||
|
||||
void InnerCollectionChanged(object sender, NotifyCollectionChangedEventArgs args)
|
||||
{
|
||||
// TODO hartez 2018/07/31 16:02:50 Handle the rest of these cases
|
||||
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;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
|
@ -53,24 +63,90 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
|
||||
void Add(NotifyCollectionChangedEventArgs args)
|
||||
{
|
||||
// TODO hartez 2018-07-31 01:47 PM Figure out what scenarios might cause a NewStartingIndex of -1
|
||||
// I'm worried that the IndexOf lookup could cause problems when the list has duplicate items
|
||||
var startIndex = args.NewStartingIndex > -1 ? args.NewStartingIndex : _innerSource.IndexOf(args.NewItems[0]);
|
||||
var startIndex = args.NewStartingIndex > -1 ? args.NewStartingIndex : _itemsSource.IndexOf(args.NewItems[0]);
|
||||
|
||||
for (int n = args.NewItems.Count - 1; n >= 0; n--)
|
||||
var count = args.NewItems.Count;
|
||||
|
||||
for(int n = 0; n < count; n++)
|
||||
{
|
||||
Insert(startIndex, new ItemTemplateContext(_itemTemplate, args.NewItems[n], _container));
|
||||
}
|
||||
}
|
||||
|
||||
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 > -1 ? args.OldStartingIndex : _innerSource.IndexOf(args.OldItems[0]);
|
||||
var startIndex = args.OldStartingIndex;
|
||||
|
||||
for (int n = 0; n < args.OldItems.Count; n++)
|
||||
if (startIndex < 0)
|
||||
{
|
||||
RemoveAt(startIndex);
|
||||
// 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 = new ItemTemplateContext(_itemTemplate, args.NewItems[n], _container);
|
||||
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();
|
||||
for (int n = 0; n < _itemsSource.Count; n++)
|
||||
{
|
||||
Items.Add(new ItemTemplateContext(_itemTemplate, _itemsSource[n], _container));
|
||||
}
|
||||
|
||||
var reset = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset);
|
||||
OnCollectionChanged(reset);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -27,5 +27,10 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
{
|
||||
return new CGSize(_constrain.Width,_constrain.Height);
|
||||
}
|
||||
|
||||
protected override (bool, Size) NeedsContentSizeUpdate(Size currentSize)
|
||||
{
|
||||
return (false, Size.Zero);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,10 +48,10 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
|
||||
void RegisterSupplementaryViews(UICollectionElementKindSection kind)
|
||||
{
|
||||
CollectionView.RegisterClassForSupplementaryView(typeof(HorizontalTemplatedSupplementalView),
|
||||
kind, HorizontalTemplatedSupplementalView.ReuseId);
|
||||
CollectionView.RegisterClassForSupplementaryView(typeof(VerticalTemplatedSupplementalView),
|
||||
kind, VerticalTemplatedSupplementalView.ReuseId);
|
||||
CollectionView.RegisterClassForSupplementaryView(typeof(HorizontalSupplementaryView),
|
||||
kind, HorizontalSupplementaryView.ReuseId);
|
||||
CollectionView.RegisterClassForSupplementaryView(typeof(VerticalSupplementaryView),
|
||||
kind, VerticalSupplementaryView.ReuseId);
|
||||
CollectionView.RegisterClassForSupplementaryView(typeof(HorizontalDefaultSupplementalView),
|
||||
kind, HorizontalDefaultSupplementalView.ReuseId);
|
||||
CollectionView.RegisterClassForSupplementaryView(typeof(VerticalDefaultSupplementalView),
|
||||
|
@ -82,7 +82,7 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
{
|
||||
cell.Label.Text = ItemsSource.Group(indexPath).ToString();
|
||||
|
||||
if (cell is ItemsViewCell constrainedCell)
|
||||
if (cell is ItemsViewCell)
|
||||
{
|
||||
cell.ConstrainTo(ItemsViewLayout.ConstrainedDimension);
|
||||
}
|
||||
|
@ -90,34 +90,20 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
|
||||
void UpdateTemplatedSupplementaryView(TemplatedCell cell, NSString elementKind, NSIndexPath indexPath)
|
||||
{
|
||||
ApplyTemplateAndDataContext(cell, elementKind, indexPath);
|
||||
DataTemplate template = elementKind == UICollectionElementKindSectionKey.Header
|
||||
? GroupableItemsView.GroupHeaderTemplate
|
||||
: GroupableItemsView.GroupFooterTemplate;
|
||||
|
||||
if (cell is ItemsViewCell constrainedCell)
|
||||
var bindingContext = ItemsSource.Group(indexPath);
|
||||
|
||||
cell.Bind(template, bindingContext, ItemsView);
|
||||
|
||||
if (cell is ItemsViewCell)
|
||||
{
|
||||
cell.ConstrainTo(ItemsViewLayout.ConstrainedDimension);
|
||||
}
|
||||
}
|
||||
|
||||
void ApplyTemplateAndDataContext(TemplatedCell cell, NSString elementKind, NSIndexPath indexPath)
|
||||
{
|
||||
DataTemplate template;
|
||||
|
||||
if (elementKind == UICollectionElementKindSectionKey.Header)
|
||||
{
|
||||
template = GroupableItemsView.GroupHeaderTemplate;
|
||||
}
|
||||
else
|
||||
{
|
||||
template = GroupableItemsView.GroupFooterTemplate;
|
||||
}
|
||||
|
||||
var templateElement = template.CreateContent() as View;
|
||||
var renderer = CreateRenderer(templateElement);
|
||||
|
||||
BindableObject.SetInheritedBindingContext(renderer.Element, ItemsSource.Group(indexPath));
|
||||
cell.SetRenderer(renderer);
|
||||
}
|
||||
|
||||
string DetermineViewReuseId(NSString elementKind)
|
||||
{
|
||||
if (elementKind == UICollectionElementKindSectionKey.Header)
|
||||
|
@ -139,8 +125,8 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
}
|
||||
|
||||
return ItemsViewLayout.ScrollDirection == UICollectionViewScrollDirection.Horizontal
|
||||
? HorizontalTemplatedSupplementalView.ReuseId
|
||||
: VerticalTemplatedSupplementalView.ReuseId;
|
||||
? HorizontalSupplementaryView.ReuseId
|
||||
: VerticalSupplementaryView.ReuseId;
|
||||
}
|
||||
|
||||
internal CGSize GetReferenceSizeForHeader(UICollectionView collectionView, UICollectionViewLayout layout, nint section)
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
using CoreGraphics;
|
||||
using Foundation;
|
||||
|
||||
namespace Xamarin.Forms.Platform.iOS
|
||||
{
|
||||
internal abstract partial class HeightConstrainedTemplatedCell : TemplatedCell
|
||||
{
|
||||
[Export("initWithFrame:")]
|
||||
public HeightConstrainedTemplatedCell(CGRect frame) : base(frame)
|
||||
{
|
||||
}
|
||||
|
||||
public override void ConstrainTo(CGSize constraint)
|
||||
{
|
||||
ConstrainedDimension = constraint.Height;
|
||||
Layout(constraint);
|
||||
}
|
||||
|
||||
protected override (bool, Size) NeedsContentSizeUpdate(Size currentSize)
|
||||
{
|
||||
var size = Size.Zero;
|
||||
|
||||
if (VisualElementRenderer?.Element == null)
|
||||
{
|
||||
return (false, size);
|
||||
}
|
||||
|
||||
var bounds = VisualElementRenderer.Element.Bounds;
|
||||
|
||||
if (bounds.Width <= 0 || bounds.Height <= 0)
|
||||
{
|
||||
return (false, size);
|
||||
}
|
||||
|
||||
var desiredBounds = VisualElementRenderer.Element.Measure(double.PositiveInfinity, bounds.Height,
|
||||
MeasureFlags.IncludeMargins);
|
||||
|
||||
if (desiredBounds.Request.Width == currentSize.Width)
|
||||
{
|
||||
// Nothing in the cell needs more room, so leave it as it is
|
||||
return (false, size);
|
||||
}
|
||||
|
||||
return (true, desiredBounds.Request);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,27 +3,21 @@ using Foundation;
|
|||
|
||||
namespace Xamarin.Forms.Platform.iOS
|
||||
{
|
||||
internal sealed class HorizontalTemplatedCell : TemplatedCell
|
||||
internal sealed class HorizontalCell : HeightConstrainedTemplatedCell
|
||||
{
|
||||
public static NSString ReuseId = new NSString("Xamarin.Forms.Platform.iOS.HorizontalTemplatedCell");
|
||||
public static NSString ReuseId = new NSString("Xamarin.Forms.Platform.iOS.HorizontalCell");
|
||||
|
||||
[Export("initWithFrame:")]
|
||||
public HorizontalTemplatedCell(CGRect frame) : base(frame)
|
||||
public HorizontalCell(CGRect frame) : base(frame)
|
||||
{
|
||||
}
|
||||
|
||||
public override CGSize Measure()
|
||||
{
|
||||
var measure = VisualElementRenderer.Element.Measure(double.PositiveInfinity,
|
||||
var measure = VisualElementRenderer.Element.Measure(double.PositiveInfinity,
|
||||
ConstrainedDimension, MeasureFlags.IncludeMargins);
|
||||
|
||||
return new CGSize(measure.Request.Width, ConstrainedDimension);
|
||||
}
|
||||
|
||||
public override void ConstrainTo(CGSize constraint)
|
||||
{
|
||||
ConstrainedDimension = constraint.Height;
|
||||
Layout(constraint);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,12 +3,12 @@ using Foundation;
|
|||
|
||||
namespace Xamarin.Forms.Platform.iOS
|
||||
{
|
||||
public class HorizontalTemplatedSupplementalView : TemplatedCell
|
||||
internal sealed class HorizontalSupplementaryView : HeightConstrainedTemplatedCell
|
||||
{
|
||||
public static NSString ReuseId = new NSString("Xamarin.Forms.Platform.iOS.HorizontalTemplatedSupplementalView");
|
||||
public static NSString ReuseId = new NSString("Xamarin.Forms.Platform.iOS.HorizontalSupplementaryView");
|
||||
|
||||
[Export("initWithFrame:")]
|
||||
public HorizontalTemplatedSupplementalView(CGRect frame) : base(frame)
|
||||
public HorizontalSupplementaryView(CGRect frame) : base(frame)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -22,11 +22,5 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
|
||||
return new CGSize(width, ConstrainedDimension);
|
||||
}
|
||||
|
||||
public override void ConstrainTo(CGSize constraint)
|
||||
{
|
||||
ConstrainedDimension = constraint.Height;
|
||||
Layout(constraint);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Foundation;
|
||||
using UIKit;
|
||||
using Xamarin.Forms.Internals;
|
||||
|
@ -199,12 +198,13 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
|
||||
protected virtual void UpdateTemplatedCell(TemplatedCell cell, NSIndexPath indexPath)
|
||||
{
|
||||
ApplyTemplateAndDataContext(cell, indexPath);
|
||||
cell.ContentSizeChanged -= CellContentSizeChanged;
|
||||
|
||||
if (cell is ItemsViewCell constrainedCell)
|
||||
{
|
||||
ItemsViewLayout.PrepareCellForLayout(constrainedCell);
|
||||
}
|
||||
cell.Bind(ItemsView, ItemsSource[indexPath]);
|
||||
|
||||
cell.ContentSizeChanged += CellContentSizeChanged;
|
||||
|
||||
ItemsViewLayout.PrepareCellForLayout(cell);
|
||||
}
|
||||
|
||||
public virtual NSIndexPath GetIndexForItem(object item)
|
||||
|
@ -217,28 +217,6 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
return ItemsSource[index];
|
||||
}
|
||||
|
||||
void ApplyTemplateAndDataContext(TemplatedCell cell, NSIndexPath indexPath)
|
||||
{
|
||||
var template = ItemsView.ItemTemplate;
|
||||
var item = ItemsSource[indexPath];
|
||||
|
||||
// Run this through the extension method in case it's really a DataTemplateSelector
|
||||
template = template.SelectDataTemplate(item, ItemsView);
|
||||
|
||||
// Create the content and renderer for the view and
|
||||
var view = template.CreateContent() as View;
|
||||
var renderer = CreateRenderer(view);
|
||||
cell.SetRenderer(renderer);
|
||||
|
||||
// Bind the view to the data item
|
||||
view.BindingContext = ItemsSource[indexPath];
|
||||
|
||||
// And make sure it's a "child" of the ItemsView
|
||||
ItemsView.AddLogicalChild(view);
|
||||
|
||||
cell.ContentSizeChanged += CellContentSizeChanged;
|
||||
}
|
||||
|
||||
void CellContentSizeChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (_disposed)
|
||||
|
@ -247,43 +225,13 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
Layout?.InvalidateLayout();
|
||||
}
|
||||
|
||||
internal void PrepareCellForRemoval(UICollectionViewCell cell)
|
||||
{
|
||||
if (cell is TemplatedCell templatedCell)
|
||||
{
|
||||
templatedCell.ContentSizeChanged -= CellContentSizeChanged;
|
||||
|
||||
var oldView = templatedCell.VisualElementRenderer?.Element;
|
||||
if (oldView != null)
|
||||
{
|
||||
oldView.BindingContext = null;
|
||||
ItemsView.RemoveLogicalChild(oldView);
|
||||
}
|
||||
|
||||
templatedCell.PrepareForRemoval();
|
||||
}
|
||||
}
|
||||
|
||||
protected IVisualElementRenderer CreateRenderer(View view)
|
||||
{
|
||||
if (view == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(view));
|
||||
}
|
||||
|
||||
var renderer = Platform.CreateRenderer(view);
|
||||
Platform.SetRenderer(view, renderer);
|
||||
|
||||
return renderer;
|
||||
}
|
||||
|
||||
protected virtual string DetermineCellReuseId()
|
||||
{
|
||||
if (ItemsView.ItemTemplate != null)
|
||||
{
|
||||
return ItemsViewLayout.ScrollDirection == UICollectionViewScrollDirection.Horizontal
|
||||
? HorizontalTemplatedCell.ReuseId
|
||||
: VerticalTemplatedCell.ReuseId;
|
||||
? HorizontalCell.ReuseId
|
||||
: VerticalCell.ReuseId;
|
||||
}
|
||||
|
||||
return ItemsViewLayout.ScrollDirection == UICollectionViewScrollDirection.Horizontal
|
||||
|
@ -323,9 +271,9 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
{
|
||||
CollectionView.RegisterClassForCell(typeof(HorizontalDefaultCell), HorizontalDefaultCell.ReuseId);
|
||||
CollectionView.RegisterClassForCell(typeof(VerticalDefaultCell), VerticalDefaultCell.ReuseId);
|
||||
CollectionView.RegisterClassForCell(typeof(HorizontalTemplatedCell),
|
||||
HorizontalTemplatedCell.ReuseId);
|
||||
CollectionView.RegisterClassForCell(typeof(VerticalTemplatedCell), VerticalTemplatedCell.ReuseId);
|
||||
CollectionView.RegisterClassForCell(typeof(HorizontalCell),
|
||||
HorizontalCell.ReuseId);
|
||||
CollectionView.RegisterClassForCell(typeof(VerticalCell), VerticalCell.ReuseId);
|
||||
}
|
||||
|
||||
bool IsHorizontal => (ItemsView?.ItemsLayout as ItemsLayout)?.Orientation == ItemsLayoutOrientation.Horizontal;
|
||||
|
@ -462,7 +410,7 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
{
|
||||
// Create the native renderer for the view, and keep the actual Forms element (if any)
|
||||
// around for updating the layout later
|
||||
var (NativeView, FormsElement) = RealizeView(view, viewTemplate);
|
||||
var (NativeView, FormsElement) = TemplateHelpers.RealizeView(view, viewTemplate, ItemsView);
|
||||
uiView = NativeView;
|
||||
formsElement = FormsElement;
|
||||
}
|
||||
|
@ -507,33 +455,5 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
_currentBackgroundIsEmptyView = false;
|
||||
}
|
||||
}
|
||||
|
||||
internal (UIView NativeView, VisualElement FormsElement) RealizeView(object view, DataTemplate viewTemplate)
|
||||
{
|
||||
if (viewTemplate != null)
|
||||
{
|
||||
// Run this through the extension method in case it's really a DataTemplateSelector
|
||||
viewTemplate = viewTemplate.SelectDataTemplate(view, ItemsView);
|
||||
|
||||
// We have a template; turn it into a Forms view
|
||||
var templateElement = viewTemplate.CreateContent() as View;
|
||||
var renderer = CreateRenderer(templateElement);
|
||||
|
||||
// and set the EmptyView as its BindingContext
|
||||
BindableObject.SetInheritedBindingContext(renderer.Element, view);
|
||||
|
||||
return (renderer.NativeView, renderer.Element);
|
||||
}
|
||||
|
||||
if (view is View formsView)
|
||||
{
|
||||
// No template, and the EmptyView is a Forms view; use that
|
||||
var renderer = CreateRenderer(formsView);
|
||||
|
||||
return (renderer.NativeView, renderer.Element);
|
||||
}
|
||||
|
||||
return (new UILabel { Text = $"{view}" }, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
using System;
|
||||
using UIKit;
|
||||
using Xamarin.Forms.Internals;
|
||||
|
||||
namespace Xamarin.Forms.Platform.iOS
|
||||
{
|
||||
internal static class TemplateHelpers
|
||||
{
|
||||
public static IVisualElementRenderer CreateRenderer(View view)
|
||||
{
|
||||
if (view == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(view));
|
||||
}
|
||||
|
||||
var renderer = Platform.CreateRenderer(view);
|
||||
Platform.SetRenderer(view, renderer);
|
||||
|
||||
return renderer;
|
||||
}
|
||||
|
||||
public static (UIView NativeView, VisualElement FormsElement) RealizeView(object view, DataTemplate viewTemplate, ItemsView itemsView)
|
||||
{
|
||||
if (viewTemplate != null)
|
||||
{
|
||||
// Run this through the extension method in case it's really a DataTemplateSelector
|
||||
viewTemplate = viewTemplate.SelectDataTemplate(view, itemsView);
|
||||
|
||||
// We have a template; turn it into a Forms view
|
||||
var templateElement = viewTemplate.CreateContent() as View;
|
||||
var renderer = CreateRenderer(templateElement);
|
||||
|
||||
// and set the EmptyView as its BindingContext
|
||||
BindableObject.SetInheritedBindingContext(renderer.Element, view);
|
||||
|
||||
return (renderer.NativeView, renderer.Element);
|
||||
}
|
||||
|
||||
if (view is View formsView)
|
||||
{
|
||||
// No template, and the EmptyView is a Forms view; use that
|
||||
var renderer = CreateRenderer(formsView);
|
||||
|
||||
return (renderer.NativeView, renderer.Element);
|
||||
}
|
||||
|
||||
return (new UILabel { Text = $"{view}" }, null);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,20 +2,28 @@
|
|||
using CoreGraphics;
|
||||
using Foundation;
|
||||
using UIKit;
|
||||
using Xamarin.Forms.Internals;
|
||||
|
||||
namespace Xamarin.Forms.Platform.iOS
|
||||
{
|
||||
public abstract class TemplatedCell : ItemsViewCell
|
||||
{
|
||||
public event EventHandler<EventArgs> ContentSizeChanged;
|
||||
|
||||
protected nfloat ConstrainedDimension;
|
||||
|
||||
DataTemplate _currentTemplate;
|
||||
|
||||
// Keep track of the cell size so we can verify whether a measure invalidation
|
||||
// actually changed the size of the cell
|
||||
Size _size;
|
||||
|
||||
[Export("initWithFrame:")]
|
||||
protected TemplatedCell(CGRect frame) : base(frame)
|
||||
{
|
||||
}
|
||||
|
||||
public IVisualElementRenderer VisualElementRenderer { get; private set; }
|
||||
internal IVisualElementRenderer VisualElementRenderer { get; private set; }
|
||||
|
||||
public override void ConstrainTo(nfloat constant)
|
||||
{
|
||||
|
@ -35,7 +43,9 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
nativeView.Frame = new CGRect(CGPoint.Empty, size);
|
||||
|
||||
// Layout the Forms element
|
||||
VisualElementRenderer.Element.Layout(nativeView.Frame.ToRectangle());
|
||||
var nativeBounds = nativeView.Frame.ToRectangle();
|
||||
VisualElementRenderer.Element.Layout(nativeBounds);
|
||||
_size = nativeBounds.Size;
|
||||
|
||||
// Adjust the preferred attributes to include space for the Forms element
|
||||
preferredAttributes.Frame = new CGRect(preferredAttributes.Frame.Location, size);
|
||||
|
@ -43,13 +53,55 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
return preferredAttributes;
|
||||
}
|
||||
|
||||
public override void PrepareForReuse()
|
||||
public void Bind(ItemsView itemsView, object bindingContext)
|
||||
{
|
||||
base.PrepareForReuse();
|
||||
ClearSubviews();
|
||||
var template = itemsView.ItemTemplate;
|
||||
|
||||
// Run this through the extension method in case it's really a DataTemplateSelector
|
||||
template = template.SelectDataTemplate(bindingContext, itemsView);
|
||||
|
||||
Bind(template, bindingContext, itemsView);
|
||||
}
|
||||
|
||||
public void SetRenderer(IVisualElementRenderer renderer)
|
||||
public void Bind(DataTemplate template, object bindingContext, ItemsView itemsView)
|
||||
{
|
||||
var oldElement = VisualElementRenderer?.Element;
|
||||
|
||||
if (template != _currentTemplate)
|
||||
{
|
||||
// Remove the old view, if it exists
|
||||
if (oldElement != null)
|
||||
{
|
||||
oldElement.MeasureInvalidated -= MeasureInvalidated;
|
||||
itemsView.RemoveLogicalChild(oldElement);
|
||||
ClearSubviews();
|
||||
_size = Size.Zero;
|
||||
}
|
||||
|
||||
// Create the content and renderer for the view
|
||||
var view = template.CreateContent() as View;
|
||||
var renderer = TemplateHelpers.CreateRenderer(view);
|
||||
SetRenderer(renderer);
|
||||
}
|
||||
|
||||
var currentElement = VisualElementRenderer?.Element;
|
||||
|
||||
// Bind the view to the data item
|
||||
currentElement.BindingContext = bindingContext;
|
||||
|
||||
if (template != _currentTemplate)
|
||||
{
|
||||
// And make the Element a "child" of the ItemsView
|
||||
// We deliberately do this _after_ setting the binding context for the new element;
|
||||
// if we do it before, the element briefly inherits the ItemsView's bindingcontext and we
|
||||
// emit a bunch of needless binding errors
|
||||
itemsView.AddLogicalChild(currentElement);
|
||||
}
|
||||
|
||||
_currentTemplate = template;
|
||||
}
|
||||
|
||||
void SetRenderer(IVisualElementRenderer renderer)
|
||||
{
|
||||
VisualElementRenderer = renderer;
|
||||
var nativeView = VisualElementRenderer.NativeView;
|
||||
|
@ -99,31 +151,24 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
}
|
||||
}
|
||||
|
||||
protected abstract (bool, Size) NeedsContentSizeUpdate(Size currentSize);
|
||||
|
||||
void MeasureInvalidated(object sender, EventArgs args)
|
||||
{
|
||||
if (VisualElementRenderer?.Element == null)
|
||||
var (needsUpdate, toSize) = NeedsContentSizeUpdate(_size);
|
||||
|
||||
if (!needsUpdate)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var bounds = VisualElementRenderer.Element.Bounds;
|
||||
|
||||
if (bounds.Width <= 0 || bounds.Height <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Cache the size for next time
|
||||
_size = toSize;
|
||||
|
||||
// Let the controller know that things need to be laid out again
|
||||
OnContentSizeChanged();
|
||||
}
|
||||
|
||||
public void PrepareForRemoval()
|
||||
{
|
||||
if (VisualElementRenderer?.Element != null)
|
||||
{
|
||||
VisualElementRenderer.Element.MeasureInvalidated -= MeasureInvalidated;
|
||||
}
|
||||
}
|
||||
|
||||
protected void OnContentSizeChanged()
|
||||
{
|
||||
ContentSizeChanged?.Invoke(this, EventArgs.Empty);
|
||||
|
|
|
@ -140,8 +140,6 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
if (collectionView.ContentOffset.Y >= actualHeight || collectionView.ContentOffset.Y < 0)
|
||||
return;
|
||||
}
|
||||
|
||||
ItemsViewController.PrepareCellForRemoval(cell);
|
||||
}
|
||||
|
||||
public override CGSize GetReferenceSizeForHeader(UICollectionView collectionView, UICollectionViewLayout layout, nint section)
|
||||
|
|
|
@ -1,29 +1,23 @@
|
|||
using CoreGraphics;
|
||||
using CoreGraphics;
|
||||
using Foundation;
|
||||
|
||||
namespace Xamarin.Forms.Platform.iOS
|
||||
{
|
||||
internal sealed class VerticalTemplatedCell : TemplatedCell
|
||||
internal sealed class VerticalCell : WidthConstrainedTemplatedCell
|
||||
{
|
||||
public static NSString ReuseId = new NSString("Xamarin.Forms.Platform.iOS.VerticalTemplatedCell");
|
||||
public static NSString ReuseId = new NSString("Xamarin.Forms.Platform.iOS.VerticalCell");
|
||||
|
||||
[Export("initWithFrame:")]
|
||||
public VerticalTemplatedCell(CGRect frame) : base(frame)
|
||||
public VerticalCell(CGRect frame) : base(frame)
|
||||
{
|
||||
}
|
||||
|
||||
public override CGSize Measure()
|
||||
{
|
||||
var measure = VisualElementRenderer.Element.Measure(ConstrainedDimension,
|
||||
var measure = VisualElementRenderer.Element.Measure(ConstrainedDimension,
|
||||
double.PositiveInfinity, MeasureFlags.IncludeMargins);
|
||||
|
||||
return new CGSize(ConstrainedDimension, measure.Request.Height);
|
||||
}
|
||||
|
||||
public override void ConstrainTo(CGSize constraint)
|
||||
{
|
||||
ConstrainedDimension = constraint.Width;
|
||||
Layout(constraint);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,12 +3,12 @@ using Foundation;
|
|||
|
||||
namespace Xamarin.Forms.Platform.iOS
|
||||
{
|
||||
public class VerticalTemplatedSupplementalView : TemplatedCell
|
||||
internal sealed class VerticalSupplementaryView : WidthConstrainedTemplatedCell
|
||||
{
|
||||
public static NSString ReuseId = new NSString("Xamarin.Forms.Platform.iOS.VerticalTemplatedSupplementalView");
|
||||
public static NSString ReuseId = new NSString("Xamarin.Forms.Platform.iOS.VerticalSupplementaryView");
|
||||
|
||||
[Export("initWithFrame:")]
|
||||
public VerticalTemplatedSupplementalView(CGRect frame) : base(frame)
|
||||
public VerticalSupplementaryView(CGRect frame) : base(frame)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -22,11 +22,5 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
|
||||
return new CGSize(ConstrainedDimension, height);
|
||||
}
|
||||
|
||||
public override void ConstrainTo(CGSize constraint)
|
||||
{
|
||||
ConstrainedDimension = constraint.Width;
|
||||
Layout(constraint);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
using CoreGraphics;
|
||||
using Foundation;
|
||||
|
||||
namespace Xamarin.Forms.Platform.iOS
|
||||
{
|
||||
internal abstract class WidthConstrainedTemplatedCell : TemplatedCell
|
||||
{
|
||||
[Export("initWithFrame:")]
|
||||
public WidthConstrainedTemplatedCell(CGRect frame) : base(frame)
|
||||
{
|
||||
}
|
||||
|
||||
public override void ConstrainTo(CGSize constraint)
|
||||
{
|
||||
ConstrainedDimension = constraint.Width;
|
||||
Layout(constraint);
|
||||
}
|
||||
|
||||
protected override (bool, Size) NeedsContentSizeUpdate(Size currentSize)
|
||||
{
|
||||
var size = Size.Zero;
|
||||
|
||||
if (VisualElementRenderer?.Element == null)
|
||||
{
|
||||
return (false, size);
|
||||
}
|
||||
|
||||
var bounds = VisualElementRenderer.Element.Bounds;
|
||||
|
||||
if (bounds.Width <= 0 || bounds.Height <= 0)
|
||||
{
|
||||
return (false, size);
|
||||
}
|
||||
|
||||
var desiredBounds = VisualElementRenderer.Element.Measure(bounds.Width, double.PositiveInfinity,
|
||||
MeasureFlags.IncludeMargins);
|
||||
|
||||
if (desiredBounds.Request.Height == currentSize.Height)
|
||||
{
|
||||
// Nothing in the cell needs more room, so leave it as it is
|
||||
return (false, size);
|
||||
}
|
||||
|
||||
return (true, desiredBounds.Request);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
using Foundation;
|
||||
using UIKit;
|
||||
|
||||
namespace Xamarin.Forms.Platform.iOS
|
||||
{
|
||||
internal static class NSObjectExtensions
|
||||
{
|
||||
public static void QueueForLater(this NSObject nsObject, Action action) =>
|
||||
nsObject.BeginInvokeOnMainThread(action);
|
||||
}
|
||||
}
|
|
@ -360,7 +360,7 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
Control.TableHeaderView = _headerRenderer.NativeView;
|
||||
}
|
||||
|
||||
async void OnScrollToRequested(object sender, ScrollToRequestedEventArgs e)
|
||||
void OnScrollToRequested(object sender, ScrollToRequestedEventArgs e)
|
||||
{
|
||||
if (Superview == null)
|
||||
{
|
||||
|
@ -386,15 +386,17 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
Control.Layer.RemoveAllAnimations();
|
||||
//iOS11 hack
|
||||
if (Forms.IsiOS11OrNewer)
|
||||
{
|
||||
await Task.Delay(1);
|
||||
}
|
||||
Control.ScrollToRow(NSIndexPath.FromRowSection(index, 0), position, e.ShouldAnimate);
|
||||
this.QueueForLater(() =>
|
||||
{
|
||||
if (Control != null && !_disposed)
|
||||
Control.ScrollToRow(NSIndexPath.FromRowSection(index, 0), position, e.ShouldAnimate);
|
||||
});
|
||||
else
|
||||
Control.ScrollToRow(NSIndexPath.FromRowSection(index, 0), position, e.ShouldAnimate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void UpdateFooter()
|
||||
{
|
||||
var footer = ListView.FooterElement;
|
||||
|
@ -1490,6 +1492,9 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
//This also forces the spinner color to be correct if we started refreshing immediately after changing it.
|
||||
UpdateContentOffset(TableView.ContentOffset.Y - _refresh.Frame.Height, () =>
|
||||
{
|
||||
if (_refresh == null)
|
||||
return;
|
||||
|
||||
_refresh.BeginRefreshing();
|
||||
//hack: when we don't have cells in our UITableView the spinner fails to appear
|
||||
CheckContentSize();
|
||||
|
|
|
@ -111,6 +111,7 @@
|
|||
<Compile Include="CollectionView\EmptySource.cs" />
|
||||
<Compile Include="CollectionView\GroupableItemsViewController.cs" />
|
||||
<Compile Include="CollectionView\GroupableItemsViewRenderer.cs" />
|
||||
<Compile Include="CollectionView\HorizontalCell.cs" />
|
||||
<Compile Include="CollectionView\HorizontalDefaultSupplementalView.cs" />
|
||||
<Compile Include="CollectionView\HorizontalTemplatedHeaderView.cs" />
|
||||
<Compile Include="CollectionView\IItemsViewSource.cs" />
|
||||
|
@ -124,7 +125,9 @@
|
|||
<Compile Include="CollectionView\ScrollToPositionExtensions.cs" />
|
||||
<Compile Include="CollectionView\SelectableItemsViewController.cs" />
|
||||
<Compile Include="CollectionView\SelectableItemsViewRenderer.cs" />
|
||||
<Compile Include="CollectionView\TemplateHelpers.cs" />
|
||||
<Compile Include="CollectionView\UICollectionViewDelegator.cs" />
|
||||
<Compile Include="CollectionView\VerticalCell.cs" />
|
||||
<Compile Include="CollectionView\VerticalDefaultCell.cs" />
|
||||
<Compile Include="CollectionView\GridViewLayout.cs" />
|
||||
<Compile Include="CollectionView\ItemsViewLayout.cs" />
|
||||
|
@ -134,10 +137,10 @@
|
|||
<Compile Include="CollectionView\PropertyChangedEventArgsExtensions.cs" />
|
||||
<Compile Include="CollectionView\SnapHelpers.cs" />
|
||||
<Compile Include="CollectionView\TemplatedCell.cs" />
|
||||
<Compile Include="CollectionView\HorizontalTemplatedCell.cs" />
|
||||
<Compile Include="CollectionView\HeightConstrainedTemplatedCell.cs" />
|
||||
<Compile Include="CollectionView\VerticalDefaultSupplementalView.cs" />
|
||||
<Compile Include="CollectionView\VerticalTemplatedCell.cs" />
|
||||
<Compile Include="CollectionView\VerticalTemplatedHeaderView.cs" />
|
||||
<Compile Include="CollectionView\WidthConstrainedTemplatedCell.cs" />
|
||||
<Compile Include="CollectionView\VerticalSupplementaryView.cs" />
|
||||
<Compile Include="DisposeHelpers.cs" />
|
||||
<Compile Include="EffectUtilities.cs" />
|
||||
<Compile Include="ExportCellAttribute.cs" />
|
||||
|
@ -145,6 +148,7 @@
|
|||
<Compile Include="ExportRendererAttribute.cs" />
|
||||
<Compile Include="Extensions\ArrayExtensions.cs" />
|
||||
<Compile Include="Extensions\FlowDirectionExtensions.cs" />
|
||||
<Compile Include="Extensions\NSObjectExtensions.cs" />
|
||||
<Compile Include="Extensions\PlatformConfigurationExtensions.cs" />
|
||||
<Compile Include="Extensions\LabelExtensions.cs" />
|
||||
<Compile Include="Extensions\VisualElementExtensions.cs" />
|
||||
|
|
|
@ -167,7 +167,7 @@ namespace Xamarin.Forms.Xaml.UnitTests
|
|||
Assert.That(page.Content.BackgroundColor, Is.EqualTo(Color.Red));
|
||||
}
|
||||
|
||||
[Test][Ignore]
|
||||
[Test][Ignore(nameof(ImplicitStyleAppliedToMissingType))]
|
||||
public void ImplicitStyleAppliedToMissingType()
|
||||
{
|
||||
XamlLoader.FallbackTypeResolver = (p, type) => type ?? typeof(Button);
|
||||
|
@ -224,7 +224,7 @@ namespace Xamarin.Forms.Xaml.UnitTests
|
|||
Assert.That(myButton.BackgroundColor, Is.Not.EqualTo(Color.Red));
|
||||
}
|
||||
|
||||
[Test][Ignore]
|
||||
[Test][Ignore(nameof(StyleTargetingMissingTypeNotAppliedToFallbackType))]
|
||||
public void StyleTargetingMissingTypeNotAppliedToFallbackType()
|
||||
{
|
||||
XamlLoader.FallbackTypeResolver = (p, type) => type ?? typeof(Button);
|
||||
|
|
|
@ -113,16 +113,17 @@ namespace Xamarin.Forms.Xaml.UnitTests
|
|||
"Release";
|
||||
#endif
|
||||
|
||||
var dir = Path.GetFullPath(
|
||||
Path.Combine(
|
||||
TestContext.CurrentContext.TestDirectory, "Xamarin.Forms.Controls.dll"));
|
||||
var xamlg = new XamlGTask()
|
||||
{
|
||||
BuildEngine = new DummyBuildEngine(),
|
||||
AssemblyName = "test",
|
||||
Language = "C#",
|
||||
XamlFiles = new[] { item },
|
||||
OutputFiles = new [] { new TaskItem(xamlOutputFile) },
|
||||
References = Path.GetFullPath(
|
||||
Path.Combine(
|
||||
Directory.GetCurrentDirectory(), "Xamarin.Forms.Controls.dll"))
|
||||
OutputFiles = new[] { new TaskItem(xamlOutputFile) },
|
||||
References = dir
|
||||
};
|
||||
|
||||
var generator = new XamlGenerator(item, xamlg.Language, xamlg.AssemblyName, xamlOutputFile, xamlg.References, null);
|
||||
|
|
|
@ -795,8 +795,12 @@ namespace Xamarin.Forms.Xaml.UnitTests
|
|||
var bindingType = XamlParser.GetElementType(new XmlType("http://xamarin.com/schemas/2014/forms", "Binding", null), null, null, out var ex);
|
||||
Assert.That(ex, Is.Null);
|
||||
Assert.That(bindingType, Is.EqualTo(typeof(BindingExtension)));
|
||||
|
||||
var bindingTypeRef = new XmlType("http://xamarin.com/schemas/2014/forms", "Binding", null).GetTypeReference(ModuleDefinition.CreateModule("foo", ModuleKind.Dll), null);
|
||||
var module = ModuleDefinition.CreateModule("foo", new ModuleParameters()
|
||||
{
|
||||
AssemblyResolver = new MockAssemblyResolver(),
|
||||
Kind = ModuleKind.Dll,
|
||||
});
|
||||
var bindingTypeRef = new XmlType("http://xamarin.com/schemas/2014/forms", "Binding", null).GetTypeReference(module, null);
|
||||
Assert.That(bindingType.FullName, Is.EqualTo("Xamarin.Forms.Xaml.BindingExtension"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
using Microsoft.Build.Locator;
|
||||
using Mono.Cecil;
|
||||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml.Linq;
|
||||
using static Xamarin.Forms.MSBuild.UnitTests.MSBuildXmlExtensions;
|
||||
|
||||
|
@ -117,7 +119,6 @@ namespace Xamarin.Forms.MSBuild.UnitTests
|
|||
/// <param name="sdkStyle">If true, uses a new SDK-style project</param>
|
||||
XElement NewProject (bool sdkStyle)
|
||||
{
|
||||
var path = Path.GetTempFileName ();
|
||||
var project = NewElement ("Project");
|
||||
|
||||
var propertyGroup = NewElement ("PropertyGroup");
|
||||
|
@ -136,6 +137,7 @@ namespace Xamarin.Forms.MSBuild.UnitTests
|
|||
propertyGroup.Add (NewElement ("OutputType").WithValue ("Library"));
|
||||
propertyGroup.Add (NewElement ("OutputPath").WithValue ("bin\\Debug"));
|
||||
propertyGroup.Add (NewElement ("TargetFrameworkVersion").WithValue ("v4.7"));
|
||||
propertyGroup.Add(NewElement("RootNamespace").WithValue("test"));
|
||||
}
|
||||
propertyGroup.Add(NewElement("_XFBuildTasksLocation").WithValue($"{testDirectory}\\"));
|
||||
|
||||
|
@ -195,8 +197,19 @@ namespace Xamarin.Forms.MSBuild.UnitTests
|
|||
}
|
||||
}
|
||||
|
||||
void Build (string projectFile, string target = "Build", string additionalArgs = "")
|
||||
string Build (string projectFile, string target = "Build", string additionalArgs = "", bool shouldSucceed = true)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
void onData(object s, DataReceivedEventArgs e)
|
||||
{
|
||||
lock (builder)
|
||||
if (e.Data != null)
|
||||
{
|
||||
builder.AppendLine(e.Data);
|
||||
Console.WriteLine(e.Data);
|
||||
}
|
||||
};
|
||||
|
||||
var psi = new ProcessStartInfo {
|
||||
FileName = FindMSBuild (),
|
||||
Arguments = $"/v:normal /nologo {projectFile} /t:{target} /bl {additionalArgs}",
|
||||
|
@ -208,14 +221,19 @@ namespace Xamarin.Forms.MSBuild.UnitTests
|
|||
WorkingDirectory = tempDirectory,
|
||||
};
|
||||
using (var p = new Process { StartInfo = psi }) {
|
||||
p.ErrorDataReceived += (s, e) => Console.Error.WriteLine (e.Data);
|
||||
p.OutputDataReceived += (s, e) => Console.WriteLine (e.Data);
|
||||
p.ErrorDataReceived += onData;
|
||||
p.OutputDataReceived += onData;
|
||||
|
||||
p.Start ();
|
||||
p.BeginErrorReadLine ();
|
||||
p.BeginOutputReadLine ();
|
||||
p.WaitForExit ();
|
||||
Assert.AreEqual (0, p.ExitCode, "MSBuild exited with {0}", p.ExitCode);
|
||||
if (shouldSucceed)
|
||||
Assert.AreEqual(0, p.ExitCode, "MSBuild exited with {0}", p.ExitCode);
|
||||
else
|
||||
Assert.AreNotEqual(0, p.ExitCode, "MSBuild exited with {0}", p.ExitCode);
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -250,6 +268,40 @@ namespace Xamarin.Forms.MSBuild.UnitTests
|
|||
AssertExists (Path.Combine (intermediateDirectory, "XamlC.stamp"));
|
||||
}
|
||||
|
||||
// Tests the XFXamlCValidateOnly=True MSBuild property
|
||||
[Test]
|
||||
public void ValidateOnly([Values(false, true)] bool sdkStyle)
|
||||
{
|
||||
var project = NewProject(sdkStyle);
|
||||
project.Add(AddFile("MainPage.xaml", "EmbeddedResource", Xaml.MainPage));
|
||||
var projectFile = Path.Combine(tempDirectory, "test.csproj");
|
||||
project.Save(projectFile);
|
||||
RestoreIfNeeded(projectFile, sdkStyle);
|
||||
Build(projectFile, additionalArgs: "/p:XFXamlCValidateOnly=True");
|
||||
|
||||
var testDll = Path.Combine(intermediateDirectory, "test.dll");
|
||||
AssertExists(testDll, nonEmpty: true);
|
||||
using (var assembly = AssemblyDefinition.ReadAssembly(testDll))
|
||||
{
|
||||
// XAML files should remain as EmbeddedResource
|
||||
var resources = assembly.MainModule.Resources.OfType<EmbeddedResource>().Select(e => e.Name).ToArray();
|
||||
CollectionAssert.Contains(resources, "test.MainPage.xaml");
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ValidateOnly_WithErrors([Values(false, true)] bool sdkStyle)
|
||||
{
|
||||
var project = NewProject(sdkStyle);
|
||||
project.Add(AddFile("MainPage.xaml", "EmbeddedResource", Xaml.MainPage.Replace ("</ContentPage>", "<NotARealThing/></ContentPage>")));
|
||||
var projectFile = Path.Combine(tempDirectory, "test.csproj");
|
||||
project.Save(projectFile);
|
||||
RestoreIfNeeded(projectFile, sdkStyle);
|
||||
|
||||
string log = Build(projectFile, additionalArgs: "/p:XFXamlCValidateOnly=True", shouldSucceed: false);
|
||||
StringAssert.Contains("MainPage.xaml(7,6): error : Position 7:6. Type NotARealThing not found", log);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that XamlG and XamlC targets skip, as well as checking IncrementalClean doesn't delete generated files
|
||||
/// </summary>
|
||||
|
@ -488,15 +540,15 @@ namespace Xamarin.Forms.MSBuild.UnitTests
|
|||
AssertExists (Path.Combine (intermediateDirectory, "XamlC.stamp"));
|
||||
}
|
||||
|
||||
[Test, ExpectedException (typeof(AssertionException))]
|
||||
public void InvalidXml ([Values (false, true)] bool sdkStyle)
|
||||
[Test]
|
||||
public void InvalidXml([Values(false, true)] bool sdkStyle)
|
||||
{
|
||||
var project = NewProject (sdkStyle);
|
||||
project.Add (AddFile ("MainPage.xaml", "EmbeddedResource", "notxmlatall"));
|
||||
var projectFile = Path.Combine (tempDirectory, "test.csproj");
|
||||
project.Save (projectFile);
|
||||
RestoreIfNeeded (projectFile, sdkStyle);
|
||||
Build (projectFile);
|
||||
var project = NewProject(sdkStyle);
|
||||
project.Add(AddFile("MainPage.xaml", "EmbeddedResource", "notxmlatall"));
|
||||
var projectFile = Path.Combine(tempDirectory, "test.csproj");
|
||||
project.Save(projectFile);
|
||||
RestoreIfNeeded(projectFile, sdkStyle);
|
||||
Assert.Throws<AssertionException>(() => Build(projectFile));
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
using Mono.Cecil;
|
||||
using NUnit.Framework;
|
||||
using System.IO;
|
||||
|
||||
namespace Xamarin.Forms.Xaml.UnitTests
|
||||
{
|
||||
public class MockAssemblyResolver : BaseAssemblyResolver
|
||||
{
|
||||
public override AssemblyDefinition Resolve(AssemblyNameReference name)
|
||||
{
|
||||
AssemblyDefinition assembly;
|
||||
var localPath = Path.GetFullPath(Path.Combine(TestContext.CurrentContext.TestDirectory, $"{name.Name}.dll"));
|
||||
if (File.Exists(localPath))
|
||||
assembly = AssemblyDefinition.ReadAssembly(localPath);
|
||||
else
|
||||
assembly = base.Resolve(name);
|
||||
return assembly;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -30,7 +30,7 @@ namespace Xamarin.Forms.Xaml.UnitTests
|
|||
KeepXamlResources = true,
|
||||
OptimizeIL = true,
|
||||
DebugSymbols = false,
|
||||
ReadOnly = true,
|
||||
ValidateOnly = true,
|
||||
Type = type.FullName,
|
||||
BuildEngine = new MSBuild.UnitTests.DummyBuildEngine()
|
||||
};
|
||||
|
|
|
@ -46,7 +46,7 @@ namespace Xamarin.Forms.Xaml.UnitTests
|
|||
}
|
||||
|
||||
[Test]
|
||||
[Ignore]
|
||||
[Ignore(nameof(XamlCIs20TimesFasterThanXaml))]
|
||||
public void XamlCIs20TimesFasterThanXaml ()
|
||||
{
|
||||
var swXamlC = new Stopwatch ();
|
||||
|
@ -66,7 +66,7 @@ namespace Xamarin.Forms.Xaml.UnitTests
|
|||
}
|
||||
|
||||
[Test]
|
||||
[Ignore]
|
||||
[Ignore(nameof(XamlCIsNotMuchSlowerThanCode))]
|
||||
public void XamlCIsNotMuchSlowerThanCode ()
|
||||
{
|
||||
var swXamlC = new Stopwatch ();
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<RootNamespace>Xamarin.Forms.Xaml.UnitTests</RootNamespace>
|
||||
<AssemblyName>Xamarin.Forms.Xaml.UnitTests</AssemblyName>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<NoWarn>0672;0219;0414</NoWarn>
|
||||
<NoWarn>0672;0219;0414;CS0436</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||
|
@ -19,8 +19,9 @@
|
|||
<ProjectReference Include="..\Xamarin.Forms.Build.Tasks\Xamarin.Forms.Build.Tasks.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="NUnit" Version="2.6.4" />
|
||||
<PackageReference Include="NUnit" Version="3.12.0" />
|
||||
<PackageReference Include="Microsoft.Build.Locator" Version="1.2.6" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="3.15.1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\Xamarin.Forms.Core.UnitTests\MockDispatcherProvider.cs">
|
||||
|
|
|
@ -6,6 +6,7 @@ using Mono.Cecil;
|
|||
using Xamarin.Forms.Build.Tasks;
|
||||
|
||||
using NUnit.Framework;
|
||||
using Xamarin.Forms.Xaml.UnitTests;
|
||||
|
||||
namespace Xamarin.Forms.XamlcUnitTests
|
||||
{
|
||||
|
@ -31,7 +32,11 @@ namespace Xamarin.Forms.XamlcUnitTests
|
|||
[SetUp]
|
||||
public void SetUp ()
|
||||
{
|
||||
module = ModuleDefinition.CreateModule ("foo", ModuleKind.Dll);
|
||||
module = ModuleDefinition.CreateModule("foo", new ModuleParameters()
|
||||
{
|
||||
AssemblyResolver = new MockAssemblyResolver(),
|
||||
Kind = ModuleKind.Dll,
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
|
|
@ -7,6 +7,7 @@ using Xamarin.Forms.Build.Tasks;
|
|||
|
||||
using NUnit.Framework;
|
||||
using System.Collections.Generic;
|
||||
using Xamarin.Forms.Xaml.UnitTests;
|
||||
|
||||
namespace Xamarin.Forms.XamlcUnitTests
|
||||
{
|
||||
|
@ -33,7 +34,11 @@ namespace Xamarin.Forms.XamlcUnitTests
|
|||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
module = ModuleDefinition.CreateModule("foo", ModuleKind.Dll);
|
||||
module = ModuleDefinition.CreateModule("foo", new ModuleParameters()
|
||||
{
|
||||
AssemblyResolver = new MockAssemblyResolver(),
|
||||
Kind = ModuleKind.Dll,
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
|
||||
using Mono.Cecil;
|
||||
|
@ -7,6 +6,7 @@ using Xamarin.Forms.Build.Tasks;
|
|||
|
||||
using NUnit.Framework;
|
||||
using System.Collections.Generic;
|
||||
using Xamarin.Forms.Xaml.UnitTests;
|
||||
|
||||
namespace Xamarin.Forms.XamlcUnitTests
|
||||
{
|
||||
|
@ -23,9 +23,13 @@ namespace Xamarin.Forms.XamlcUnitTests
|
|||
}
|
||||
|
||||
[SetUp]
|
||||
public void SetUp ()
|
||||
public void SetUp()
|
||||
{
|
||||
module = ModuleDefinition.CreateModule ("foo", ModuleKind.Dll);
|
||||
module = ModuleDefinition.CreateModule("foo", new ModuleParameters()
|
||||
{
|
||||
AssemblyResolver = new MockAssemblyResolver(),
|
||||
Kind = ModuleKind.Dll,
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
|
|
@ -2,7 +2,7 @@ using System;
|
|||
using NUnit.Framework.Constraints;
|
||||
|
||||
namespace Xamarin.Forms.Xaml.UnitTests
|
||||
{
|
||||
{
|
||||
public class XamlParseExceptionConstraint : ExceptionTypeConstraint
|
||||
{
|
||||
bool haslineinfo;
|
||||
|
@ -10,13 +10,14 @@ namespace Xamarin.Forms.Xaml.UnitTests
|
|||
int lineposition;
|
||||
Func<string, bool> messagePredicate;
|
||||
|
||||
XamlParseExceptionConstraint (bool haslineinfo) : base (typeof (XamlParseException))
|
||||
XamlParseExceptionConstraint(bool haslineinfo) : base(typeof(XamlParseException))
|
||||
{
|
||||
this.haslineinfo = haslineinfo;
|
||||
DisplayName = "xamlparse";
|
||||
}
|
||||
|
||||
public XamlParseExceptionConstraint () : this (false)
|
||||
public override string DisplayName => "xamlparse";
|
||||
|
||||
public XamlParseExceptionConstraint() : this(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -27,9 +28,8 @@ namespace Xamarin.Forms.Xaml.UnitTests
|
|||
this.messagePredicate = messagePredicate;
|
||||
}
|
||||
|
||||
public override bool Matches (object actual)
|
||||
protected override bool Matches (object actual)
|
||||
{
|
||||
this.actual = actual;
|
||||
if (!base.Matches (actual))
|
||||
return false;
|
||||
var xmlInfo = ((XamlParseException)actual).XmlInfo;
|
||||
|
@ -43,25 +43,30 @@ namespace Xamarin.Forms.Xaml.UnitTests
|
|||
return xmlInfo.LineNumber == linenumber && xmlInfo.LinePosition == lineposition;
|
||||
}
|
||||
|
||||
public override void WriteDescriptionTo (MessageWriter writer)
|
||||
public override string Description
|
||||
{
|
||||
base.WriteDescriptionTo (writer);
|
||||
if (haslineinfo)
|
||||
writer.Write (string.Format (" line {0}, position {1}", linenumber, lineposition));
|
||||
}
|
||||
|
||||
public override void WriteActualValueTo (MessageWriter writer)
|
||||
{
|
||||
var ex = actual as XamlParseException;
|
||||
writer.WriteActualValue ((actual == null) ? null : actual.GetType ());
|
||||
if (ex != null) {
|
||||
if (ex.XmlInfo != null && ex.XmlInfo.HasLineInfo ())
|
||||
writer.Write (" line {0}, position {1}", ex.XmlInfo.LineNumber, ex.XmlInfo.LinePosition);
|
||||
else
|
||||
writer.Write (" no line info");
|
||||
writer.WriteLine (" ({0})", ex.Message);
|
||||
writer.Write (ex.StackTrace);
|
||||
get
|
||||
{
|
||||
if (haslineinfo)
|
||||
{
|
||||
return string.Format($"{base.Description} line {linenumber}, position {lineposition}");
|
||||
}
|
||||
return base.Description;
|
||||
}
|
||||
}
|
||||
|
||||
//public override void WriteActualValueTo (MessageWriter writer)
|
||||
//{
|
||||
// var ex = actual as XamlParseException;
|
||||
// writer.WriteActualValue ((actual == null) ? null : actual.GetType ());
|
||||
// if (ex != null) {
|
||||
// if (ex.XmlInfo != null && ex.XmlInfo.HasLineInfo ())
|
||||
// writer.Write (" line {0}, position {1}", ex.XmlInfo.LineNumber, ex.XmlInfo.LinePosition);
|
||||
// else
|
||||
// writer.Write (" no line info");
|
||||
// writer.WriteLine (" ({0})", ex.Message);
|
||||
// writer.Write (ex.StackTrace);
|
||||
// }
|
||||
//}
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@ using System.Linq;
|
|||
using System.Reflection;
|
||||
using System.Xml;
|
||||
using Xamarin.Forms.Internals;
|
||||
using Xamarin.Forms.Xaml.Diagnostics;
|
||||
using Xamarin.Forms.Xaml.Internals;
|
||||
|
||||
using static System.String;
|
||||
|
@ -344,16 +345,25 @@ namespace Xamarin.Forms.Xaml
|
|||
return;
|
||||
|
||||
//If it's a BindableProberty, SetValue
|
||||
if (xpe == null && TrySetValue(xamlelement, property, attached, value, lineInfo, serviceProvider, out xpe))
|
||||
if (xpe == null && TrySetValue(xamlelement, property, attached, value, lineInfo, serviceProvider, out xpe)) {
|
||||
VisualDiagnostics.RegisterSourceInfo(value, null, ((IXmlLineInfo)node).LineNumber, ((IXmlLineInfo)node).LinePosition);
|
||||
VisualDiagnostics.SendVisualTreeChanged(xamlelement, value);
|
||||
return;
|
||||
}
|
||||
|
||||
//If we can assign that value to a normal property, let's do it
|
||||
if (xpe == null && TrySetProperty(xamlelement, localName, value, lineInfo, serviceProvider, context, out xpe))
|
||||
if (xpe == null && TrySetProperty(xamlelement, localName, value, lineInfo, serviceProvider, context, out xpe)) {
|
||||
VisualDiagnostics.RegisterSourceInfo(value, null, ((IXmlLineInfo)node).LineNumber, ((IXmlLineInfo)node).LinePosition);
|
||||
VisualDiagnostics.SendVisualTreeChanged(xamlelement, value);
|
||||
return;
|
||||
}
|
||||
|
||||
//If it's an already initialized property, add to it
|
||||
if (xpe == null && TryAddToProperty(xamlelement, propertyName, value, xKey, lineInfo, serviceProvider, context, out xpe))
|
||||
if (xpe == null && TryAddToProperty(xamlelement, propertyName, value, xKey, lineInfo, serviceProvider, context, out xpe)) {
|
||||
VisualDiagnostics.RegisterSourceInfo(value, null, ((IXmlLineInfo)node).LineNumber, ((IXmlLineInfo)node).LinePosition);
|
||||
VisualDiagnostics.SendVisualTreeChanged(xamlelement, value);
|
||||
return;
|
||||
}
|
||||
|
||||
xpe = xpe ?? new XamlParseException($"Cannot assign property \"{localName}\": Property does not exist, or is not assignable, or mismatching type between value and property", lineInfo);
|
||||
if (context.ExceptionHandler != null)
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Xamarin.Forms.Xaml.Diagnostics
|
||||
{
|
||||
static class DebuggerHelper
|
||||
{
|
||||
internal static bool _mockDebuggerIsAttached;
|
||||
public static bool DebuggerIsAttached => _mockDebuggerIsAttached || Debugger.IsAttached;
|
||||
}
|
||||
}
|
|
@ -4,7 +4,11 @@ namespace Xamarin.Forms.Xaml.Diagnostics
|
|||
internal static class ResourceDictionaryDiagnostics
|
||||
{
|
||||
internal static void OnStaticResourceResolved(ResourceDictionary resourceDictionary, string key, object targetObject, object targetProperty)
|
||||
=> StaticResourceResolved?.Invoke(resourceDictionary, new StaticResourceResolvedEventArgs(resourceDictionary, key, targetObject, targetProperty));
|
||||
{
|
||||
if (DebuggerHelper.DebuggerIsAttached)
|
||||
StaticResourceResolved?.Invoke(resourceDictionary, new StaticResourceResolvedEventArgs(resourceDictionary, key, targetObject, targetProperty));
|
||||
}
|
||||
|
||||
public static event EventHandler<StaticResourceResolvedEventArgs> StaticResourceResolved;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Xamarin.Forms.Xaml.Diagnostics
|
||||
{
|
||||
class VisualDiagnostics
|
||||
{
|
||||
static ConditionalWeakTable<object, XamlSourceInfo> sourceInfos = new ConditionalWeakTable<object, XamlSourceInfo>();
|
||||
internal static void RegisterSourceInfo(object target, Uri uri, int lineNumber, int linePosition)
|
||||
{
|
||||
if (DebuggerHelper.DebuggerIsAttached)
|
||||
sourceInfos.Add(target, new XamlSourceInfo(uri, lineNumber, linePosition));
|
||||
}
|
||||
|
||||
internal static void SendVisualTreeChanged(object parent, object child)
|
||||
{
|
||||
if (DebuggerHelper.DebuggerIsAttached)
|
||||
VisualTreeChanged?.Invoke(parent, new VisualTreeChangeEventArgs(parent, child, -1, VisualTreeChangeType.Add));
|
||||
}
|
||||
|
||||
public static event EventHandler<VisualTreeChangeEventArgs> VisualTreeChanged;
|
||||
public static XamlSourceInfo GetXamlSourceInfo(object obj) => sourceInfos.TryGetValue(obj, out var sourceinfo) ? sourceinfo : null;
|
||||
}
|
||||
|
||||
class XamlSourceInfo
|
||||
{
|
||||
public XamlSourceInfo(Uri sourceUri, int lineNumber, int linePosition)
|
||||
{
|
||||
SourceUri = sourceUri;
|
||||
LineNumber = lineNumber;
|
||||
LinePosition = linePosition;
|
||||
}
|
||||
|
||||
public Uri SourceUri { get; }
|
||||
public int LineNumber { get; }
|
||||
public int LinePosition { get; }
|
||||
|
||||
public void Deconstruct(out Uri sourceUri, out int lineNumber, out int linePosition)
|
||||
{
|
||||
sourceUri = SourceUri;
|
||||
lineNumber = LineNumber;
|
||||
linePosition = LinePosition;
|
||||
}
|
||||
}
|
||||
|
||||
class VisualTreeChangeEventArgs : EventArgs
|
||||
{
|
||||
public VisualTreeChangeEventArgs(object parent, object child, int childIndex, VisualTreeChangeType changeType)
|
||||
{
|
||||
Parent = parent;
|
||||
Child = child;
|
||||
ChildIndex = childIndex;
|
||||
ChangeType = changeType;
|
||||
}
|
||||
|
||||
public object Parent { get; }
|
||||
public object Child { get; }
|
||||
public int ChildIndex { get; }
|
||||
public VisualTreeChangeType ChangeType { get; }
|
||||
}
|
||||
|
||||
enum VisualTreeChangeType
|
||||
{
|
||||
Add = 0,
|
||||
Remove = 1
|
||||
}
|
||||
}
|
|
@ -10,8 +10,6 @@ namespace Xamarin.Forms.Xaml
|
|||
[ContentProperty(nameof(Key))]
|
||||
public sealed class StaticResourceExtension : IMarkupExtension
|
||||
{
|
||||
internal static bool _mockDebuggerIsAttached; //for unit testing
|
||||
|
||||
public string Key { get; set; }
|
||||
public object ProvideValue(IServiceProvider serviceProvider)
|
||||
{
|
||||
|
@ -28,8 +26,7 @@ namespace Xamarin.Forms.Xaml
|
|||
&& !TryGetApplicationLevelResource(Key, out resource, out resourceDictionary))
|
||||
throw new XamlParseException($"StaticResource not found for key {Key}", xmlLineInfo);
|
||||
|
||||
if (System.Diagnostics.Debugger.IsAttached || _mockDebuggerIsAttached)
|
||||
Diagnostics.ResourceDictionaryDiagnostics.OnStaticResourceResolved(resourceDictionary, Key, valueProvider.TargetObject, valueProvider.TargetProperty);
|
||||
Diagnostics.ResourceDictionaryDiagnostics.OnStaticResourceResolved(resourceDictionary, Key, valueProvider.TargetObject, valueProvider.TargetProperty);
|
||||
|
||||
return CastTo(resource, valueProvider.TargetProperty);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче