зеркало из https://github.com/DeGsoft/maui-linux.git
Merge branch 'main' into main-handler
This commit is contained in:
Коммит
9dcdee2ace
|
@ -0,0 +1,23 @@
|
|||
name: Backport Trigger
|
||||
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
|
||||
jobs:
|
||||
launchBackportBuild:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.issue.pull_request != '' && contains(github.event.comment.body, '@vs-mobiletools-engineering-service2 backport')
|
||||
|
||||
steps:
|
||||
- uses: xamarin/backport-bot-action@v1.0
|
||||
with:
|
||||
pull_request_url: ${{ github.event.issue.pull_request.url }}
|
||||
comment_body: ${{ github.event.comment.body }}
|
||||
comment_author: ${{ github.actor }}
|
||||
github_repository: ${{ github.repository }}
|
||||
ado_organization: ${{ secrets.ADO_PROJECTCOLLECTION }}
|
||||
ado_project: ${{ secrets.ADO_PROJECT }}
|
||||
backport_pipeline_id: ${{ secrets.BACKPORT_PIPELINEID }}
|
||||
ado_build_pat: ${{ secrets.ADO_BUILDPAT }}
|
||||
github_account_pat: ${{ secrets.SERVICEACCOUNT_PAT }}
|
|
@ -0,0 +1,22 @@
|
|||
name: Rebase Trigger
|
||||
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
|
||||
jobs:
|
||||
launchBackportBuild:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.issue.pull_request != '' && contains(github.event.comment.body, '@vs-mobiletools-engineering-service2 rebase')
|
||||
|
||||
steps:
|
||||
- uses: xamarin/rebase-bot-action@v1.0
|
||||
with:
|
||||
pull_request_url: ${{ github.event.issue.pull_request.url }}
|
||||
comment_author: ${{ github.actor }}
|
||||
github_repository: ${{ github.repository }}
|
||||
ado_organization: ${{ secrets.ADO_PROJECTCOLLECTION }}
|
||||
ado_project: ${{ secrets.ADO_PROJECT }}
|
||||
rebase_pipeline_id: 13926
|
||||
ado_build_pat: ${{ secrets.ADO_BUILDPAT }}
|
||||
github_account_pat: ${{ secrets.SERVICEACCOUNT_PAT }}
|
|
@ -1346,4 +1346,4 @@ public string ParseDevOpsInputs(string nunitWhere)
|
|||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<controls:TestContentPage
|
||||
xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
xmlns:controls="clr-namespace:Xamarin.Forms.Controls"
|
||||
x:Class="Xamarin.Forms.Controls.Issues.Issue12848"
|
||||
Title="Issue 12848">
|
||||
<StackLayout>
|
||||
<Label
|
||||
Padding="12"
|
||||
BackgroundColor="Black"
|
||||
TextColor="White"
|
||||
Text="Swipe the CarouselView to select the item numbered 2. Then, tap the Hide Button to hide the Carousel and the Show Button to show the Carousel again. If the position of the Carousel is the same as before hiding, the test has passed."/>
|
||||
<CarouselView
|
||||
AutomationId="TestCarouselView"
|
||||
x:Name="carousel"
|
||||
HorizontalOptions="Center"
|
||||
ItemsSource="{Binding}">
|
||||
<CarouselView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Label
|
||||
Text="{Binding}"
|
||||
FontSize="96"
|
||||
HorizontalTextAlignment="Center"/>
|
||||
</DataTemplate>
|
||||
</CarouselView.ItemTemplate>
|
||||
</CarouselView>
|
||||
<Label
|
||||
AutomationId="CarouselPosition"
|
||||
Text="{Binding Source={x:Reference carousel}, Path=Position}"
|
||||
HorizontalOptions="Center"/>
|
||||
<Button
|
||||
AutomationId="HideButton"
|
||||
Text="Hide CarouselView"
|
||||
Clicked="OnHideButtonClicked"/>
|
||||
<Button
|
||||
AutomationId="ShowButton"
|
||||
Text="Show CarouselView"
|
||||
Clicked="OnShowButtonClicked"/>
|
||||
</StackLayout>
|
||||
</controls:TestContentPage>
|
|
@ -0,0 +1,53 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Xamarin.Forms.CustomAttributes;
|
||||
using Xamarin.Forms.Internals;
|
||||
|
||||
#if UITEST
|
||||
using Xamarin.Forms.Core.UITests;
|
||||
using NUnit.Framework;
|
||||
#endif
|
||||
|
||||
namespace Xamarin.Forms.Controls.Issues
|
||||
{
|
||||
[Preserve(AllMembers = true)]
|
||||
[Issue(IssueTracker.Github, 12848, "[Bug] CarouselView position resets when visibility toggled",
|
||||
PlatformAffected.Android)]
|
||||
public partial class Issue12848 : TestContentPage
|
||||
{
|
||||
protected override void Init()
|
||||
{
|
||||
#if APP
|
||||
InitializeComponent();
|
||||
|
||||
BindingContext = new List<int> { 1, 2, 3 };
|
||||
#endif
|
||||
}
|
||||
|
||||
#if APP
|
||||
void OnShowButtonClicked(object sender, EventArgs e)
|
||||
{
|
||||
carousel.IsVisible = true;
|
||||
}
|
||||
|
||||
void OnHideButtonClicked(object sender, EventArgs e)
|
||||
{
|
||||
carousel.IsVisible = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if UITEST
|
||||
[Test]
|
||||
public void Issue12848Test()
|
||||
{
|
||||
RunningApp.WaitForElement("TestCarouselView");
|
||||
RunningApp.SwipeRightToLeft();
|
||||
Assert.AreEqual(1, int.Parse(RunningApp.Query(q => q.Marked("CarouselPosition"))[0].Text));
|
||||
RunningApp.Tap("HideButton");
|
||||
RunningApp.Tap("ShowButton");
|
||||
Assert.AreEqual(1, int.Parse(RunningApp.Query(q => q.Marked("CarouselPosition"))[0].Text));
|
||||
RunningApp.Screenshot("Test passed");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<local:TestContentPage
|
||||
xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d"
|
||||
Title="Test 13436" xmlns:local="using:Xamarin.Forms.Controls"
|
||||
x:Class="Xamarin.Forms.Controls.Issues.Issue13436">
|
||||
<StackLayout>
|
||||
<Label
|
||||
Padding="12"
|
||||
BackgroundColor="Black"
|
||||
TextColor="White"
|
||||
Text="Without exceptions, the test has passed."/>
|
||||
<CarouselView
|
||||
x:Name="Carousel"
|
||||
AutomationId="CarouselId"
|
||||
HorizontalScrollBarVisibility="Never"
|
||||
Loop="False"
|
||||
VerticalOptions="Center">
|
||||
<CarouselView.ItemsLayout>
|
||||
<LinearItemsLayout
|
||||
Orientation="Horizontal"
|
||||
SnapPointsAlignment="Center"
|
||||
SnapPointsType="MandatorySingle" />
|
||||
</CarouselView.ItemsLayout>
|
||||
<CarouselView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Grid BackgroundColor="{Binding Color}">
|
||||
<Grid Margin="20">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Label
|
||||
Grid.Row="0"
|
||||
Margin="0,0,0,20"
|
||||
Text="{Binding Name}"
|
||||
TextColor="Black" />
|
||||
<Label
|
||||
Grid.Row="1"
|
||||
Margin="0,0,0,20"
|
||||
Text="{Binding Desc}"
|
||||
TextColor="Black" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</CarouselView.ItemTemplate>
|
||||
</CarouselView>
|
||||
</StackLayout>
|
||||
</local:TestContentPage>
|
|
@ -0,0 +1,91 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Xamarin.Forms.CustomAttributes;
|
||||
using Xamarin.Forms.Internals;
|
||||
|
||||
#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, 13436,
|
||||
"[Bug] Java.Lang.IllegalArgumentException in CarouselView adjusting PeekAreaInsets in OnSizeAllocated using XF 5.0",
|
||||
PlatformAffected.Android)]
|
||||
public partial class Issue13436 : TestContentPage
|
||||
{
|
||||
public Issue13436()
|
||||
{
|
||||
#if APP
|
||||
InitializeComponent();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if APP
|
||||
double _prevWidth;
|
||||
|
||||
protected override void OnAppearing()
|
||||
{
|
||||
base.OnAppearing();
|
||||
|
||||
Carousel.ItemsSource = new List<Issue13436Model>
|
||||
{
|
||||
new Issue13436Model
|
||||
{
|
||||
Name = "N1",
|
||||
Desc = "D1",
|
||||
Color = Color.Yellow
|
||||
},
|
||||
new Issue13436Model
|
||||
{
|
||||
Name = "N2",
|
||||
Desc = "D2",
|
||||
Color = Color.Orange
|
||||
},
|
||||
new Issue13436Model
|
||||
{
|
||||
Name = "N3",
|
||||
Desc = "D3",
|
||||
Color = Color.AliceBlue
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected override void OnSizeAllocated(double width, double height)
|
||||
{
|
||||
base.OnSizeAllocated(width, height);
|
||||
|
||||
if (Math.Abs(width - _prevWidth) < .1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_prevWidth = width;
|
||||
Carousel.PeekAreaInsets = width * .15;
|
||||
}
|
||||
#endif
|
||||
protected override void Init()
|
||||
{
|
||||
}
|
||||
|
||||
#if UITEST && __ANDROID__
|
||||
[Test]
|
||||
public void ChangePeekAreaInsetsInOnSizeAllocatedTest()
|
||||
{
|
||||
RunningApp.WaitForElement("CarouselId");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
[Preserve(AllMembers = true)]
|
||||
public class Issue13436Model
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Desc { get; set; }
|
||||
public Color Color { get; set; }
|
||||
public double Scale { get; set; }
|
||||
}
|
||||
}
|
|
@ -1684,6 +1684,7 @@
|
|||
<Compile Include="$(MSBuildThisFileDirectory)Issue12777.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Issue11911.xaml.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Issue11691.xaml.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Issue12848.xaml.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Issue12315.xaml.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Issue12912.xaml.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Issue12910.xaml.cs" />
|
||||
|
@ -1706,6 +1707,7 @@
|
|||
<Compile Include="$(MSBuildThisFileDirectory)ShellFlyoutBackground.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)ShellFlyoutContentOffest.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)ShellFlyoutContentWithZeroMargin.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Issue13436.xaml.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Bugzilla22229.xaml">
|
||||
|
@ -2064,6 +2066,9 @@
|
|||
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue11691.xaml">
|
||||
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue12848.xaml">
|
||||
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue12315.xaml">
|
||||
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
|
||||
</EmbeddedResource>
|
||||
|
@ -2103,6 +2108,9 @@
|
|||
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue12911.xaml">
|
||||
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue13436.xaml">
|
||||
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Bugzilla27417Xaml.xaml">
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<ResourceDictionary
|
||||
xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
|
||||
<Color x:Key="notBlue">Red</Color>
|
||||
<Color x:Key="AccentColor">#FF4B14</Color>
|
||||
</ResourceDictionary>
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Mono.Cecil;
|
||||
using Mono.Cecil.Cil;
|
||||
using Xamarin.Forms.Build.Tasks;
|
||||
|
@ -13,7 +14,7 @@ namespace Xamarin.Forms.Core.XamlC
|
|||
{
|
||||
public IEnumerable<Instruction> ConvertFromString(string value, ILContext context, BaseNode node)
|
||||
{
|
||||
var module = context.Body.Method.Module;
|
||||
var currentModule = context.Body.Method.Module;
|
||||
var body = context.Body;
|
||||
|
||||
INode rootNode = node;
|
||||
|
@ -22,7 +23,23 @@ namespace Xamarin.Forms.Core.XamlC
|
|||
|
||||
var rdNode = node.Parent as IElementNode;
|
||||
|
||||
var rootTargetPath = XamlCTask.GetPathForType(module, ((ILRootNode)rootNode).TypeReference);
|
||||
var rootTargetPath = XamlCTask.GetPathForType(currentModule, ((ILRootNode)rootNode).TypeReference);
|
||||
|
||||
var module = currentModule;
|
||||
string asmName = null;
|
||||
if (value.Contains(";assembly="))
|
||||
{
|
||||
var parts = value.Split(new[] { ";assembly=" }, StringSplitOptions.RemoveEmptyEntries);
|
||||
value = parts[0];
|
||||
asmName = parts[1];
|
||||
if (currentModule.Assembly.Name.Name != asmName)
|
||||
{
|
||||
var ar = currentModule.AssemblyReferences.FirstOrDefault(ar => ar.Name == asmName);
|
||||
if (ar == null)
|
||||
throw new BuildException(BuildExceptionCode.ResourceMissing, node, null, value);
|
||||
module = currentModule.AssemblyResolver.Resolve(ar).MainModule;
|
||||
}
|
||||
}
|
||||
var uri = new Uri(value, UriKind.Relative);
|
||||
|
||||
var resourcePath = ResourceDictionary.RDSourceTypeConverter.GetResourcePath(uri, rootTargetPath);
|
||||
|
@ -36,25 +53,38 @@ namespace Xamarin.Forms.Core.XamlC
|
|||
|
||||
//abuse the converter, produce some side effect, but leave the stack untouched
|
||||
//public void SetAndLoadSource(Uri value, string resourceID, Assembly assembly, System.Xml.IXmlLineInfo lineInfo)
|
||||
foreach (var instruction in context.Variables[rdNode].LoadAs(module.GetTypeDefinition(resourceDictionaryType), module))
|
||||
foreach (var instruction in context.Variables[rdNode].LoadAs(currentModule.GetTypeDefinition(resourceDictionaryType), currentModule))
|
||||
yield return instruction;
|
||||
//reappend assembly= in all cases, see other RD converter
|
||||
if (!string.IsNullOrEmpty(asmName))
|
||||
value = $"{value};assembly={asmName}";
|
||||
else
|
||||
value = $"{value};assembly={((ILRootNode)rootNode).TypeReference.Module.Assembly.Name.Name}";
|
||||
foreach (var instruction in (new UriTypeConverter()).ConvertFromString(value, context, node))
|
||||
yield return instruction; //the Uri
|
||||
|
||||
//keep the Uri for later
|
||||
yield return Create(Dup);
|
||||
var uriVarDef = new VariableDefinition(module.ImportReference(("System", "System", "Uri")));
|
||||
var uriVarDef = new VariableDefinition(currentModule.ImportReference(("System", "System", "Uri")));
|
||||
body.Variables.Add(uriVarDef);
|
||||
yield return Create(Stloc, uriVarDef);
|
||||
yield return Create(Ldstr, resourcePath); //resourcePath
|
||||
yield return Create(Ldtoken, module.ImportReference(((ILRootNode)rootNode).TypeReference));
|
||||
yield return Create(Call, module.ImportMethodReference(("mscorlib", "System", "Type"), methodName: "GetTypeFromHandle", parameterTypes: new[] { ("mscorlib", "System", "RuntimeTypeHandle") }, isStatic: true));
|
||||
yield return Create(Call, module.ImportMethodReference(("mscorlib", "System.Reflection", "IntrospectionExtensions"), methodName: "GetTypeInfo", parameterTypes: new[] { ("mscorlib", "System", "Type") }, isStatic: true));
|
||||
yield return Create(Callvirt, module.ImportPropertyGetterReference(("mscorlib", "System.Reflection", "TypeInfo"), propertyName: "Assembly", flatten: true));
|
||||
|
||||
if (!string.IsNullOrEmpty(asmName))
|
||||
{
|
||||
yield return Create(Ldstr, asmName);
|
||||
yield return Create(Call, currentModule.ImportMethodReference(("mscorlib", "System.Reflection", "Assembly"), methodName: "Load", parameterTypes: new[] { ("mscorlib", "System", "String") }, isStatic: true));
|
||||
}
|
||||
else //we could use assembly.Load in the 'else' part too, but I don't want to change working code right now
|
||||
{
|
||||
yield return Create(Ldtoken, currentModule.ImportReference(((ILRootNode)rootNode).TypeReference));
|
||||
yield return Create(Call, currentModule.ImportMethodReference(("mscorlib", "System", "Type"), methodName: "GetTypeFromHandle", parameterTypes: new[] { ("mscorlib", "System", "RuntimeTypeHandle") }, isStatic: true));
|
||||
yield return Create(Call, currentModule.ImportMethodReference(("mscorlib", "System.Reflection", "IntrospectionExtensions"), methodName: "GetTypeInfo", parameterTypes: new[] { ("mscorlib", "System", "Type") }, isStatic: true));
|
||||
yield return Create(Callvirt, currentModule.ImportPropertyGetterReference(("mscorlib", "System.Reflection", "TypeInfo"), propertyName: "Assembly", flatten: true));
|
||||
}
|
||||
foreach (var instruction in node.PushXmlLineInfo(context))
|
||||
yield return instruction; //lineinfo
|
||||
yield return Create(Callvirt, module.ImportMethodReference(resourceDictionaryType,
|
||||
yield return Create(Callvirt, currentModule.ImportMethodReference(resourceDictionaryType,
|
||||
methodName: "SetAndLoadSource",
|
||||
parameterTypes: new[] { ("System", "System", "Uri"), ("mscorlib", "System", "String"), ("mscorlib", "System.Reflection", "Assembly"), ("System.Xml.ReaderWriter", "System.Xml", "IXmlLineInfo") }));
|
||||
//ldloc the stored uri as return value
|
||||
|
|
|
@ -377,7 +377,7 @@ namespace Xamarin.Forms
|
|||
var element = LogicalChildren[i];
|
||||
if (element is VisualElement c)
|
||||
{
|
||||
if (c.Bounds != startingLayout[i])
|
||||
if (startingLayout.Count <= i || c.Bounds != startingLayout[i])
|
||||
{
|
||||
LayoutChanged?.Invoke(this, EventArgs.Empty);
|
||||
return;
|
||||
|
|
|
@ -175,7 +175,7 @@ namespace Xamarin.Forms
|
|||
|
||||
public int Count
|
||||
{
|
||||
get { return _innerDictionary.Count; }
|
||||
get { return _innerDictionary.Count + (_mergedInstance?.Count ?? 0); }
|
||||
}
|
||||
|
||||
bool ICollection<KeyValuePair<string, object>>.IsReadOnly
|
||||
|
@ -230,7 +230,7 @@ namespace Xamarin.Forms
|
|||
|
||||
public bool Remove(string key)
|
||||
{
|
||||
return _innerDictionary.Remove(key);
|
||||
return _innerDictionary.Remove(key) || (_mergedInstance?.Remove(key) ?? false);
|
||||
}
|
||||
|
||||
public ICollection<object> Values
|
||||
|
@ -369,10 +369,23 @@ namespace Xamarin.Forms
|
|||
|
||||
var lineInfo = (serviceProvider.GetService(typeof(Xaml.IXmlLineInfoProvider)) as Xaml.IXmlLineInfoProvider)?.XmlLineInfo;
|
||||
var rootTargetPath = XamlResourceIdAttribute.GetPathForType(rootObjectType);
|
||||
var assembly = rootObjectType.GetTypeInfo().Assembly;
|
||||
#if NETSTANDARD2_0
|
||||
if (value.Contains(";assembly="))
|
||||
{
|
||||
var parts = value.Split(new[] { ";assembly=" }, StringSplitOptions.RemoveEmptyEntries);
|
||||
value = parts[0];
|
||||
var asmName = parts[1];
|
||||
assembly = Assembly.Load(asmName);
|
||||
}
|
||||
#endif
|
||||
var uri = new Uri(value, UriKind.Relative); //we don't want file:// uris, even if they start with '/'
|
||||
var resourcePath = GetResourcePath(uri, rootTargetPath);
|
||||
|
||||
targetRD.SetAndLoadSource(uri, resourcePath, rootObjectType.GetTypeInfo().Assembly, lineInfo);
|
||||
//Re-add the assembly= in all cases, so HotReload doesn't have to make assumptions
|
||||
uri = new Uri($"{value};assembly={assembly.GetName().Name}", UriKind.Relative);
|
||||
targetRD.SetAndLoadSource(uri, resourcePath, assembly, lineInfo);
|
||||
|
||||
return uri;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ using System.Linq;
|
|||
using System.Runtime.CompilerServices;
|
||||
using System.Threading.Tasks;
|
||||
using Xamarin.Forms.Internals;
|
||||
using Xamarin.Forms.Xaml.Diagnostics;
|
||||
|
||||
namespace Xamarin.Forms
|
||||
{
|
||||
|
@ -493,6 +494,40 @@ namespace Xamarin.Forms
|
|||
return _navigationManager.GoToAsync(state, animate, false);
|
||||
}
|
||||
|
||||
public void AddLogicalChild(Element element)
|
||||
{
|
||||
if (element == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_logicalChildren.Contains(element))
|
||||
return;
|
||||
|
||||
_logicalChildren.Add(element);
|
||||
element.Parent = this;
|
||||
OnChildAdded(element);
|
||||
VisualDiagnostics.OnChildAdded(this, element);
|
||||
}
|
||||
|
||||
public void RemoveLogicalChild(Element element)
|
||||
{
|
||||
if (element == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
element.Parent = null;
|
||||
|
||||
if (!_logicalChildren.Contains(element))
|
||||
return;
|
||||
|
||||
var oldLogicalIndex = _logicalChildren.IndexOf(element);
|
||||
_logicalChildren.Remove(element);
|
||||
OnChildRemoved(element, oldLogicalIndex);
|
||||
VisualDiagnostics.OnChildRemoved(this, element, oldLogicalIndex);
|
||||
}
|
||||
|
||||
public static readonly BindableProperty CurrentItemProperty =
|
||||
BindableProperty.Create(nameof(CurrentItem), typeof(ShellItem), typeof(Shell), null, BindingMode.TwoWay,
|
||||
propertyChanging: OnCurrentItemChanging,
|
||||
|
@ -547,6 +582,11 @@ namespace Xamarin.Forms
|
|||
ShellNavigationManager _navigationManager;
|
||||
ShellFlyoutItemsManager _flyoutManager;
|
||||
|
||||
ObservableCollection<Element> _logicalChildren = new ObservableCollection<Element>();
|
||||
|
||||
internal override ReadOnlyCollection<Element> LogicalChildrenInternal =>
|
||||
new ReadOnlyCollection<Element>(_logicalChildren);
|
||||
|
||||
public Shell()
|
||||
{
|
||||
_navigationManager = new ShellNavigationManager(this);
|
||||
|
@ -566,6 +606,7 @@ namespace Xamarin.Forms
|
|||
Navigation = new NavigationImpl(this);
|
||||
Route = Routing.GenerateImplicitRoute("shell");
|
||||
Initialize();
|
||||
InternalChildren.CollectionChanged += OnInternalChildrenCollectionChanged;
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
|
@ -784,38 +825,17 @@ namespace Xamarin.Forms
|
|||
View FlyoutHeaderView
|
||||
{
|
||||
get => _flyoutHeaderView;
|
||||
set
|
||||
{
|
||||
if (_flyoutHeaderView == value)
|
||||
return;
|
||||
|
||||
if (_flyoutHeaderView != null)
|
||||
OnChildRemoved(_flyoutHeaderView, -1);
|
||||
_flyoutHeaderView = value;
|
||||
if (_flyoutHeaderView != null)
|
||||
OnChildAdded(_flyoutHeaderView);
|
||||
}
|
||||
}
|
||||
|
||||
View FlyoutFooterView
|
||||
{
|
||||
get => _flyoutFooterView;
|
||||
set
|
||||
{
|
||||
if (_flyoutFooterView == value)
|
||||
return;
|
||||
|
||||
if (_flyoutFooterView != null)
|
||||
OnChildRemoved(_flyoutFooterView, -1);
|
||||
_flyoutFooterView = value;
|
||||
if (_flyoutFooterView != null)
|
||||
OnChildAdded(_flyoutFooterView);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnBindingContextChanged()
|
||||
{
|
||||
base.OnBindingContextChanged();
|
||||
|
||||
if (FlyoutHeaderView != null)
|
||||
SetInheritedBindingContext(FlyoutHeaderView, BindingContext);
|
||||
|
||||
|
@ -871,18 +891,6 @@ namespace Xamarin.Forms
|
|||
|
||||
bool ValidDefaultShellItem(Element child) => !(child is MenuShellItem);
|
||||
|
||||
internal override IEnumerable<Element> ChildrenNotDrawnByThisElement
|
||||
{
|
||||
get
|
||||
{
|
||||
if (FlyoutHeaderView != null)
|
||||
yield return FlyoutHeaderView;
|
||||
|
||||
if (FlyoutFooterView != null)
|
||||
yield return FlyoutFooterView;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnNavigated(ShellNavigatedEventArgs args)
|
||||
{
|
||||
}
|
||||
|
@ -1094,6 +1102,18 @@ namespace Xamarin.Forms
|
|||
return null;
|
||||
}
|
||||
|
||||
|
||||
void OnInternalChildrenCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
if (e.NewItems != null)
|
||||
foreach (Element element in e.NewItems)
|
||||
AddLogicalChild(element);
|
||||
|
||||
if (e.OldItems != null)
|
||||
foreach (Element element in e.OldItems)
|
||||
RemoveLogicalChild(element);
|
||||
}
|
||||
|
||||
void NotifyFlyoutBehaviorObservers()
|
||||
{
|
||||
if (CurrentItem == null || GetVisiblePage() == null)
|
||||
|
@ -1106,56 +1126,44 @@ namespace Xamarin.Forms
|
|||
|
||||
void OnFlyoutHeaderChanged(object oldVal, object newVal)
|
||||
{
|
||||
if (FlyoutHeaderTemplate == null)
|
||||
{
|
||||
if (newVal is View newFlyoutHeader)
|
||||
FlyoutHeaderView = newFlyoutHeader;
|
||||
else
|
||||
FlyoutHeaderView = null;
|
||||
}
|
||||
ShellTemplatedViewManager.OnViewDataChanged(
|
||||
FlyoutHeaderTemplate,
|
||||
ref _flyoutHeaderView,
|
||||
newVal,
|
||||
RemoveLogicalChild,
|
||||
AddLogicalChild);
|
||||
}
|
||||
|
||||
void OnFlyoutHeaderTemplateChanged(DataTemplate oldValue, DataTemplate newValue)
|
||||
{
|
||||
if (newValue == null)
|
||||
{
|
||||
if (FlyoutHeader is View flyoutHeaderView)
|
||||
FlyoutHeaderView = flyoutHeaderView;
|
||||
else
|
||||
FlyoutHeaderView = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
var newHeaderView = (View)newValue.CreateContent(FlyoutHeader, this);
|
||||
FlyoutHeaderView = newHeaderView;
|
||||
}
|
||||
ShellTemplatedViewManager.OnViewTemplateChanged(
|
||||
newValue,
|
||||
ref _flyoutHeaderView,
|
||||
FlyoutHeader,
|
||||
RemoveLogicalChild,
|
||||
AddLogicalChild,
|
||||
this);
|
||||
}
|
||||
|
||||
void OnFlyoutFooterChanged(object oldVal, object newVal)
|
||||
{
|
||||
if (FlyoutFooterTemplate == null)
|
||||
{
|
||||
if (newVal is View newFlyoutFooter)
|
||||
FlyoutFooterView = newFlyoutFooter;
|
||||
else
|
||||
FlyoutFooterView = null;
|
||||
}
|
||||
ShellTemplatedViewManager.OnViewDataChanged(
|
||||
FlyoutFooterTemplate,
|
||||
ref _flyoutFooterView,
|
||||
newVal,
|
||||
RemoveLogicalChild,
|
||||
AddLogicalChild);
|
||||
}
|
||||
|
||||
void OnFlyoutFooterTemplateChanged(DataTemplate oldValue, DataTemplate newValue)
|
||||
{
|
||||
if (newValue == null)
|
||||
{
|
||||
if (FlyoutFooter is View flyoutFooterView)
|
||||
FlyoutFooterView = flyoutFooterView;
|
||||
else
|
||||
FlyoutFooterView = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
var newFooterView = (View)newValue.CreateContent(FlyoutFooter, this);
|
||||
FlyoutFooterView = newFooterView;
|
||||
}
|
||||
ShellTemplatedViewManager.OnViewTemplateChanged(
|
||||
newValue,
|
||||
ref _flyoutFooterView,
|
||||
FlyoutFooter,
|
||||
RemoveLogicalChild,
|
||||
AddLogicalChild,
|
||||
this);
|
||||
}
|
||||
|
||||
internal Element GetVisiblePage()
|
||||
|
@ -1194,8 +1202,15 @@ namespace Xamarin.Forms
|
|||
PropertyPropagationExtensions.PropagatePropertyChanged(propertyName, this, new[] { FlyoutHeaderView });
|
||||
if (FlyoutFooterView != null)
|
||||
PropertyPropagationExtensions.PropagatePropertyChanged(propertyName, this, new[] { FlyoutFooterView });
|
||||
if (FlyoutContentView != null)
|
||||
PropertyPropagationExtensions.PropagatePropertyChanged(propertyName, this, new[] { FlyoutContentView });
|
||||
}
|
||||
|
||||
protected override void LayoutChildren(double x, double y, double width, double height)
|
||||
{
|
||||
// Page by default tries to layout all logical children
|
||||
// we don't want this behavior with shell
|
||||
}
|
||||
|
||||
#region Shell Flyout Content
|
||||
|
||||
|
@ -1223,44 +1238,27 @@ namespace Xamarin.Forms
|
|||
View FlyoutContentView
|
||||
{
|
||||
get => _flyoutContentView;
|
||||
set
|
||||
{
|
||||
if (_flyoutContentView == value)
|
||||
return;
|
||||
|
||||
if (_flyoutContentView != null)
|
||||
OnChildRemoved(_flyoutContentView, -1);
|
||||
_flyoutContentView = value;
|
||||
if (_flyoutContentView != null)
|
||||
OnChildAdded(_flyoutContentView);
|
||||
}
|
||||
}
|
||||
|
||||
void OnFlyoutContentChanged(object oldVal, object newVal)
|
||||
{
|
||||
if (FlyoutContentTemplate == null)
|
||||
{
|
||||
if (newVal is View newFlyoutContent)
|
||||
FlyoutContentView = newFlyoutContent;
|
||||
else
|
||||
FlyoutContentView = null;
|
||||
}
|
||||
ShellTemplatedViewManager.OnViewDataChanged(
|
||||
FlyoutContentTemplate,
|
||||
ref _flyoutContentView,
|
||||
newVal,
|
||||
RemoveLogicalChild,
|
||||
AddLogicalChild);
|
||||
}
|
||||
|
||||
void OnFlyoutContentTemplateChanged(DataTemplate oldValue, DataTemplate newValue)
|
||||
{
|
||||
if (newValue == null)
|
||||
{
|
||||
if (FlyoutContent is View flyoutContentView)
|
||||
FlyoutContentView = flyoutContentView;
|
||||
else
|
||||
FlyoutContentView = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
var newContentView = (View)newValue.CreateContent(FlyoutContent, this);
|
||||
FlyoutContentView = newContentView;
|
||||
}
|
||||
ShellTemplatedViewManager.OnViewTemplateChanged(
|
||||
newValue,
|
||||
ref _flyoutContentView,
|
||||
FlyoutContent,
|
||||
RemoveLogicalChild,
|
||||
AddLogicalChild,
|
||||
this);
|
||||
}
|
||||
|
||||
static void OnFlyoutContentChanging(BindableObject bindable, object oldValue, object newValue)
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Xamarin.Forms.Internals;
|
||||
|
||||
namespace Xamarin.Forms
|
||||
{
|
||||
public static class ShellTemplatedViewManager
|
||||
{
|
||||
public static void SetView(
|
||||
ref View localView,
|
||||
View newView,
|
||||
Action<Element> OnChildRemoved,
|
||||
Action<Element> OnChildAdded)
|
||||
{
|
||||
if (localView == newView)
|
||||
return;
|
||||
|
||||
if (localView != null)
|
||||
OnChildRemoved(localView);
|
||||
localView = newView;
|
||||
if (localView != null)
|
||||
OnChildAdded(localView);
|
||||
}
|
||||
|
||||
|
||||
public static void OnViewDataChanged(
|
||||
DataTemplate currentViewTemplate,
|
||||
ref View localViewRef,
|
||||
object newViewData,
|
||||
Action<Element> OnChildRemoved,
|
||||
Action<Element> OnChildAdded)
|
||||
{
|
||||
if (currentViewTemplate == null)
|
||||
{
|
||||
SetView(ref localViewRef,
|
||||
newViewData as View,
|
||||
OnChildRemoved,
|
||||
OnChildAdded);
|
||||
}
|
||||
}
|
||||
|
||||
public static void OnViewTemplateChanged(
|
||||
DataTemplate newViewTemplate,
|
||||
ref View localViewRef,
|
||||
object currentViewData,
|
||||
Action<Element> OnChildRemoved,
|
||||
Action<Element> OnChildAdded,
|
||||
Shell shell)
|
||||
{
|
||||
View newContentView = currentViewData as View;
|
||||
if (newViewTemplate != null)
|
||||
{
|
||||
newContentView = (View)newViewTemplate.CreateContent(newViewTemplate, shell);
|
||||
}
|
||||
|
||||
SetView(ref localViewRef,
|
||||
newContentView,
|
||||
OnChildRemoved,
|
||||
OnChildAdded);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -345,7 +345,7 @@ namespace Xamarin.Forms.Core.UnitTests
|
|||
}
|
||||
|
||||
[Test]
|
||||
public void CountDoesNotIncludeMerged()
|
||||
public void CountDoesIncludeMerged()
|
||||
{
|
||||
var rd = new ResourceDictionary {
|
||||
{"baz", "Baz"},
|
||||
|
@ -353,7 +353,7 @@ namespace Xamarin.Forms.Core.UnitTests
|
|||
};
|
||||
rd.MergedWith = typeof(MyRD);
|
||||
|
||||
Assert.That(rd.Count, Is.EqualTo(2));
|
||||
Assert.That(rd.Count, Is.EqualTo(4));
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
|
|
@ -768,10 +768,10 @@ namespace Xamarin.Forms.Core.UnitTests
|
|||
shell.FlyoutHeader = null;
|
||||
shell.FlyoutHeader = layout;
|
||||
|
||||
Assert.True(shell.ChildrenNotDrawnByThisElement.Contains(layout));
|
||||
Assert.True(shell.LogicalChildren.Contains(layout));
|
||||
shell.FlyoutHeader = null;
|
||||
|
||||
Assert.False(shell.ChildrenNotDrawnByThisElement.Contains(layout));
|
||||
Assert.False(shell.LogicalChildren.Contains(layout));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" >
|
||||
<Color x:Key="Color1">Chartreuse</Color>
|
||||
</ResourceDictionary>
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<ContentPage
|
||||
xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="Xamarin.Forms.Xaml.UnitTests.Gh13209">
|
||||
<StackLayout x:Name="Root">
|
||||
<StackLayout.Resources>
|
||||
<ResourceDictionary Source="../AppResources/RD13209.xaml"/>
|
||||
</StackLayout.Resources>
|
||||
<Rectangle x:Name="MyRect" BackgroundColor="{StaticResource Color1}" WidthRequest="100" HeightRequest="100" Margin="6"/>
|
||||
<Label x:Name="MyLabel" WidthRequest="200" HeightRequest="30" Margin="6"/>
|
||||
</StackLayout>
|
||||
</ContentPage>
|
|
@ -0,0 +1,43 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Core.UnitTests;
|
||||
|
||||
namespace Xamarin.Forms.Xaml.UnitTests
|
||||
{
|
||||
public partial class Gh13209 : ContentPage
|
||||
{
|
||||
public Gh13209() => InitializeComponent();
|
||||
public Gh13209(bool useCompiledXaml)
|
||||
{
|
||||
//this stub will be replaced at compile time
|
||||
}
|
||||
|
||||
[TestFixture]
|
||||
class Tests
|
||||
{
|
||||
|
||||
[SetUp] public void Setup() => Device.PlatformServices = new MockPlatformServices();
|
||||
|
||||
[TearDown] public void TearDown() => Device.PlatformServices = null;
|
||||
|
||||
[TestCase(true), TestCase(false)]
|
||||
public void RdWithSource(bool useCompiledXaml)
|
||||
{
|
||||
var layout = new Gh13209(useCompiledXaml);
|
||||
Assert.That(layout.MyRect.BackgroundColor, Is.EqualTo(Color.Chartreuse));
|
||||
Assert.That(layout.Root.Resources.Count, Is.EqualTo(1));
|
||||
Assert.That(layout.Root.Resources.MergedDictionaries.Count, Is.EqualTo(0));
|
||||
|
||||
Assert.That(layout.Root.Resources["Color1"], Is.Not.Null);
|
||||
Assert.That(layout.Root.Resources.Remove("Color1"), Is.True);
|
||||
Assert.Throws<KeyNotFoundException>(() =>
|
||||
{
|
||||
var _ = layout.Root.Resources["Color1"];
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,6 +10,8 @@
|
|||
<ResourceDictionary Source="SharedResourceDictionary.xaml" x:Key="shortURI"/>
|
||||
<ResourceDictionary Source="./AppResources/Colors.xaml" x:Key="Colors" />
|
||||
<ResourceDictionary Source="./AppResources/CompiledColors.xaml" x:Key="CompiledColors" />
|
||||
<ResourceDictionary Source="/AppResources/Colors.xaml;assembly=Xamarin.Forms.Xaml.UnitTests" x:Key="inCurrentAssembly" />
|
||||
<ResourceDictionary Source="/AppResources.xaml;assembly=Xamarin.Forms.Controls" x:Key="inOtherAssembly" />
|
||||
</ResourceDictionary>
|
||||
</ContentPage.Resources>
|
||||
<Label x:Name="label" Style="{StaticResource sharedfoo}"/>
|
||||
|
|
|
@ -19,17 +19,8 @@ namespace Xamarin.Forms.Xaml.UnitTests
|
|||
[TestFixture]
|
||||
public class Tests
|
||||
{
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
Device.PlatformServices = new MockPlatformServices();
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
Device.PlatformServices = null;
|
||||
}
|
||||
[SetUp] public void Setup() => Device.PlatformServices = new MockPlatformServices();
|
||||
[TearDown] public void TearDown() => Device.PlatformServices = null;
|
||||
|
||||
[TestCase(false), TestCase(true)]
|
||||
public void RDWithSourceAreFound(bool useCompiledXaml)
|
||||
|
@ -42,11 +33,11 @@ namespace Xamarin.Forms.Xaml.UnitTests
|
|||
public void RelativeAndAbsoluteURI(bool useCompiledXaml)
|
||||
{
|
||||
var layout = new ResourceDictionaryWithSource(useCompiledXaml);
|
||||
Assert.That(((ResourceDictionary)layout.Resources["relURI"]).Source, Is.EqualTo(new Uri("./SharedResourceDictionary.xaml", UriKind.Relative)));
|
||||
Assert.That(((ResourceDictionary)layout.Resources["relURI"]).Source, Is.EqualTo(new Uri("./SharedResourceDictionary.xaml;assembly=Xamarin.Forms.Xaml.UnitTests", UriKind.Relative)));
|
||||
Assert.That(((ResourceDictionary)layout.Resources["relURI"])["sharedfoo"], Is.TypeOf<Style>());
|
||||
Assert.That(((ResourceDictionary)layout.Resources["absURI"]).Source, Is.EqualTo(new Uri("/SharedResourceDictionary.xaml", UriKind.Relative)));
|
||||
Assert.That(((ResourceDictionary)layout.Resources["absURI"]).Source, Is.EqualTo(new Uri("/SharedResourceDictionary.xaml;assembly=Xamarin.Forms.Xaml.UnitTests", UriKind.Relative)));
|
||||
Assert.That(((ResourceDictionary)layout.Resources["absURI"])["sharedfoo"], Is.TypeOf<Style>());
|
||||
Assert.That(((ResourceDictionary)layout.Resources["shortURI"]).Source, Is.EqualTo(new Uri("SharedResourceDictionary.xaml", UriKind.Relative)));
|
||||
Assert.That(((ResourceDictionary)layout.Resources["shortURI"]).Source, Is.EqualTo(new Uri("SharedResourceDictionary.xaml;assembly=Xamarin.Forms.Xaml.UnitTests", UriKind.Relative)));
|
||||
Assert.That(((ResourceDictionary)layout.Resources["shortURI"])["sharedfoo"], Is.TypeOf<Style>());
|
||||
Assert.That(((ResourceDictionary)layout.Resources["Colors"])["MediumGrayTextColor"], Is.TypeOf<Color>());
|
||||
Assert.That(((ResourceDictionary)layout.Resources["CompiledColors"])["MediumGrayTextColor"], Is.TypeOf<Color>());
|
||||
|
@ -73,6 +64,17 @@ namespace Xamarin.Forms.Xaml.UnitTests
|
|||
var rd = Activator.CreateInstance(type);
|
||||
Assert.That(rd as ResourceDictionary, Is.Not.Null);
|
||||
}
|
||||
|
||||
[TestCase(false), TestCase(true)]
|
||||
public void LoadResourcesWithAssembly(bool useCompiledXaml)
|
||||
{
|
||||
var layout = new ResourceDictionaryWithSource(useCompiledXaml);
|
||||
Assert.That(((ResourceDictionary)layout.Resources["inCurrentAssembly"]).Source, Is.EqualTo(new Uri("/AppResources/Colors.xaml;assembly=Xamarin.Forms.Xaml.UnitTests", UriKind.Relative)));
|
||||
Assert.That(((ResourceDictionary)layout.Resources["inCurrentAssembly"])["MediumGrayTextColor"], Is.TypeOf<Color>());
|
||||
Assert.That(((ResourceDictionary)layout.Resources["inOtherAssembly"]).Source, Is.EqualTo(new Uri("/AppResources.xaml;assembly=Xamarin.Forms.Controls", UriKind.Relative)));
|
||||
Assert.That(((ResourceDictionary)layout.Resources["inOtherAssembly"])["notBlue"], Is.TypeOf<Color>());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -334,21 +334,21 @@ namespace Xamarin.Forms.Platform.Android
|
|||
|
||||
void UpdateInitialPosition()
|
||||
{
|
||||
int position = 0;
|
||||
int itemCount = 0;
|
||||
int position;
|
||||
|
||||
if (Carousel.CurrentItem != null)
|
||||
{
|
||||
var carouselEnumerator = Carousel.ItemsSource.GetEnumerator();
|
||||
var items = new List<object>();
|
||||
|
||||
while (carouselEnumerator.MoveNext())
|
||||
{
|
||||
if(carouselEnumerator.Current == Carousel.CurrentItem)
|
||||
position = itemCount;
|
||||
|
||||
items.Add(carouselEnumerator.Current);
|
||||
itemCount++;
|
||||
}
|
||||
|
||||
position = items.IndexOf(Carousel.CurrentItem);
|
||||
Carousel.Position = position;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -64,6 +64,16 @@ namespace Xamarin.Forms.Platform.Android
|
|||
return id;
|
||||
}
|
||||
|
||||
public override void OnViewRecycled(Java.Lang.Object holder)
|
||||
{
|
||||
if (holder is ElementViewHolder evh)
|
||||
{
|
||||
evh.Element = null;
|
||||
}
|
||||
|
||||
base.OnViewRecycled(holder);
|
||||
}
|
||||
|
||||
public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
|
||||
{
|
||||
var item = _listItems[position];
|
||||
|
@ -279,6 +289,7 @@ namespace Xamarin.Forms.Platform.Android
|
|||
if (_element == value)
|
||||
return;
|
||||
|
||||
_shell.RemoveLogicalChild(View);
|
||||
if (_element != null && _element is BaseShellItem)
|
||||
{
|
||||
_element.ClearValue(AppCompat.Platform.RendererProperty);
|
||||
|
@ -287,12 +298,12 @@ namespace Xamarin.Forms.Platform.Android
|
|||
|
||||
_element = value;
|
||||
|
||||
// Set Parent after binding context so parent binding context doesn't propagate to view
|
||||
// Set binding context before calling AddLogicalChild so parent binding context doesn't propagate to view
|
||||
View.BindingContext = value;
|
||||
View.Parent = _shell;
|
||||
|
||||
if (_element != null)
|
||||
{
|
||||
_shell.AddLogicalChild(View);
|
||||
FastRenderers.AutomationPropertiesProvider.AccessibilitySettingsChanged(_itemView, value);
|
||||
_element.SetValue(AppCompat.Platform.RendererProperty, _itemView);
|
||||
_element.PropertyChanged += OnElementPropertyChanged;
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
object _previousDataContext;
|
||||
double _previousWidth;
|
||||
FrameworkElement FrameworkElement { get; set; }
|
||||
|
||||
Shell _shell;
|
||||
public ShellFlyoutItemRenderer()
|
||||
{
|
||||
this.DataContextChanged += OnDataContextChanged;
|
||||
|
@ -46,6 +46,7 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
if (_content.BindingContext is INotifyPropertyChanged inpc)
|
||||
inpc.PropertyChanged -= ShellElementPropertyChanged;
|
||||
|
||||
_shell?.RemoveLogicalChild(_content);
|
||||
_content.Cleanup();
|
||||
_content.MeasureInvalidated -= OnMeasureInvalidated;
|
||||
_content.BindingContext = null;
|
||||
|
@ -55,8 +56,8 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
|
||||
var bo = (BindableObject)args.NewValue;
|
||||
var element = bo as Element;
|
||||
var shell = element?.FindParent<Shell>();
|
||||
DataTemplate dataTemplate = (shell as IShellController)?.GetFlyoutItemDataTemplate(bo);
|
||||
_shell = element?.FindParent<Shell>();
|
||||
DataTemplate dataTemplate = (_shell as IShellController)?.GetFlyoutItemDataTemplate(bo);
|
||||
|
||||
if (bo != null)
|
||||
bo.PropertyChanged += ShellElementPropertyChanged;
|
||||
|
@ -65,7 +66,8 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
{
|
||||
_content = (View)dataTemplate.CreateContent();
|
||||
_content.BindingContext = bo;
|
||||
_content.Parent = shell;
|
||||
_shell.AddLogicalChild(_content);
|
||||
|
||||
_content.MeasureInvalidated += OnMeasureInvalidated;
|
||||
IVisualElementRenderer renderer = Platform.CreateRenderer(_content);
|
||||
Platform.SetRenderer(_content, renderer);
|
||||
|
|
|
@ -88,9 +88,24 @@ namespace Xamarin.Forms.Platform.MacOS
|
|||
if (Element == null || Control == null)
|
||||
return _defaultIsAccessibilityElement;
|
||||
|
||||
// If the user hasn't set IsInAccessibleTree then just don't do anything
|
||||
if (!Element.IsSet(AutomationProperties.IsInAccessibleTreeProperty))
|
||||
return null;
|
||||
|
||||
#if __MOBILE__
|
||||
if (!_defaultIsAccessibilityElement.HasValue)
|
||||
_defaultIsAccessibilityElement = Control.IsAccessibilityElement;
|
||||
{
|
||||
// iOS sets the default value for IsAccessibilityElement late in the layout cycle
|
||||
// But if we set it to false ourselves then that causes it to act like it's false
|
||||
|
||||
// from the docs:
|
||||
// https://developer.apple.com/documentation/objectivec/nsobject/1615141-isaccessibilityelement
|
||||
// The default value for this property is false unless the receiver is a standard UIKit control,
|
||||
// in which case the value is true.
|
||||
//
|
||||
// So we just base the default on that logic
|
||||
_defaultIsAccessibilityElement = Control.IsAccessibilityElement || Control is UIControl;
|
||||
}
|
||||
|
||||
Control.IsAccessibilityElement = (bool)((bool?)Element.GetValue(AutomationProperties.IsInAccessibleTreeProperty) ?? _defaultIsAccessibilityElement);
|
||||
#else
|
||||
|
|
|
@ -95,8 +95,8 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
if (cell == null)
|
||||
{
|
||||
var view = (View)template.CreateContent(context, _context.Shell);
|
||||
view.Parent = _context.Shell;
|
||||
view.BindingContext = context;
|
||||
view.Parent = _context.Shell;
|
||||
cell = new UIContainerCell(cellId, view);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
if (_cells != null)
|
||||
{
|
||||
foreach (var cell in _cells.Values)
|
||||
cell.Disconnect();
|
||||
cell.Disconnect(_context.Shell);
|
||||
}
|
||||
|
||||
_cells = new Dictionary<Element, UIContainerCell>();
|
||||
|
@ -57,7 +57,7 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
if (_cells != null)
|
||||
{
|
||||
foreach (var cell in _cells.Values)
|
||||
cell.Disconnect();
|
||||
cell.Disconnect(_context.Shell);
|
||||
}
|
||||
_cells = new Dictionary<Element, UIContainerCell>();
|
||||
}
|
||||
|
@ -120,18 +120,13 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
if (!_cells.TryGetValue(context, out cell))
|
||||
{
|
||||
var view = (View)template.CreateContent(context, _context.Shell);
|
||||
cell = new UIContainerCell(cellId, view);
|
||||
|
||||
// Set Parent after binding context so parent binding context doesn't propagate to view
|
||||
cell.BindingContext = context;
|
||||
view.Parent = _context.Shell;
|
||||
cell = new UIContainerCell(cellId, view, _context.Shell, context);
|
||||
}
|
||||
else
|
||||
{
|
||||
var view = _cells[context].View;
|
||||
cell.Disconnect();
|
||||
cell = new UIContainerCell(cellId, view);
|
||||
cell.BindingContext = context;
|
||||
cell = new UIContainerCell(cellId, view, _context.Shell, context);
|
||||
}
|
||||
|
||||
cell.SetAccessibilityProperties(context);
|
||||
|
|
|
@ -8,22 +8,32 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
{
|
||||
IVisualElementRenderer _renderer;
|
||||
object _bindingContext;
|
||||
|
||||
internal Action<UIContainerCell> ViewMeasureInvalidated { get; set; }
|
||||
internal NSIndexPath IndexPath { get; set; }
|
||||
internal UITableView TableView { get; set; }
|
||||
|
||||
public UIContainerCell(string cellId, View view) : base(UITableViewCellStyle.Default, cellId)
|
||||
internal UIContainerCell(string cellId, View view, Shell shell, object context) : base(UITableViewCellStyle.Default, cellId)
|
||||
{
|
||||
View = view;
|
||||
View.MeasureInvalidated += MeasureInvalidated;
|
||||
SelectionStyle = UITableViewCellSelectionStyle.None;
|
||||
|
||||
|
||||
_renderer = Platform.CreateRenderer(view);
|
||||
Platform.SetRenderer(view, _renderer);
|
||||
|
||||
ContentView.AddSubview(_renderer.NativeView);
|
||||
_renderer.NativeView.ClipsToBounds = true;
|
||||
ContentView.ClipsToBounds = true;
|
||||
|
||||
BindingContext = context;
|
||||
if (shell != null)
|
||||
shell.AddLogicalChild(View);
|
||||
}
|
||||
|
||||
|
||||
public UIContainerCell(string cellId, View view) : this(cellId, view, null, null)
|
||||
{
|
||||
}
|
||||
|
||||
void MeasureInvalidated(object sender, System.EventArgs e)
|
||||
|
@ -39,7 +49,7 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
TableView.ReloadRows(new[] { IndexPath }, UITableViewRowAnimation.Automatic);
|
||||
}
|
||||
|
||||
internal void Disconnect()
|
||||
internal void Disconnect(Shell shell = null)
|
||||
{
|
||||
ViewMeasureInvalidated = null;
|
||||
View.MeasureInvalidated -= MeasureInvalidated;
|
||||
|
@ -48,6 +58,9 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
|
||||
_bindingContext = null;
|
||||
Platform.SetRenderer(View, null);
|
||||
if (shell != null)
|
||||
shell.RemoveLogicalChild(shell);
|
||||
|
||||
View = null;
|
||||
TableView = null;
|
||||
}
|
||||
|
@ -72,7 +85,6 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
baseShell2.PropertyChanged += OnElementPropertyChanged;
|
||||
UpdateVisualState();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -223,12 +223,6 @@ namespace Xamarin.Forms.Platform.MacOS
|
|||
_controlChanging?.Invoke(this, EventArgs.Empty);
|
||||
#if __MOBILE__
|
||||
_defaultColor = uiview.BackgroundColor;
|
||||
|
||||
// UIKit UIViews created via storyboard default IsAccessibilityElement to true, BUT
|
||||
// UIViews created programmatically default IsAccessibilityElement to false.
|
||||
// We need to default to true to allow all elements to be accessible by default and
|
||||
// allow users to override this later via AutomationProperties.IsInAccessibleTree
|
||||
uiview.IsAccessibilityElement = true;
|
||||
#else
|
||||
uiview.WantsLayer = true;
|
||||
_defaultColor = uiview.Layer.BackgroundColor;
|
||||
|
|
Загрузка…
Ссылка в новой задаче