diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 41d23caf22bb..ca97b7116e2f 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -9,13 +9,13 @@ ] }, "powershell": { - "version": "7.3.4", + "version": "7.3.5", "commands": [ "pwsh" ] }, "microsoft.dotnet.xharness.cli": { - "version": "8.0.0-prerelease.23312.1", + "version": "8.0.0-prerelease.23321.2", "commands": [ "xharness" ] diff --git a/.github/workflows/dotnet-format-daily.yml b/.github/workflows/dotnet-format-daily-main.yml similarity index 95% rename from .github/workflows/dotnet-format-daily.yml rename to .github/workflows/dotnet-format-daily-main.yml index 825a0e43d66d..70074015c77b 100644 --- a/.github/workflows/dotnet-format-daily.yml +++ b/.github/workflows/dotnet-format-daily-main.yml @@ -15,12 +15,12 @@ jobs: - name: Checkout repo uses: actions/checkout@v2 with: - ref: ${{ github.head_ref }} + ref: main - name: Setup .NET Core SDK uses: actions/setup-dotnet@v3.2.0 with: - dotnet-version: 7.0.304 + dotnet-version: 8.x - name: Run dotnet format run: dotnet format .\Microsoft.Maui.sln --no-restore --exclude Templates/src BlazorWebView/src/SharedSource/BlazorWebViewDeveloperTools.cs BlazorWebView/src/SharedSource/BlazorWebViewServiceCollectionExtensions.cs Graphics/src/Graphics.Win2D/W2DCanvas.cs Graphics/src/Graphics.Win2D/W2DExtensions.cs @@ -46,3 +46,4 @@ jobs: assignees: rmarinho, jsuarezruiz reviewers: rmarinho, jsuarezruiz branch: housekeeping/fix-codeformatting + base: main diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index acd2e2b46073..9ba551a677d3 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -83,17 +83,17 @@ https://github.com/dotnet/templating 3f4da9ced34942d83054e647f3b1d9d7dde281e8 - + https://github.com/dotnet/xharness - 5dabb78620cf157a43de27e8d1b84786eb1baabc + d59c983920609fddd0d378921e36388c3bae8d00 - + https://github.com/dotnet/xharness - 5dabb78620cf157a43de27e8d1b84786eb1baabc + d59c983920609fddd0d378921e36388c3bae8d00 - + https://github.com/dotnet/xharness - 5dabb78620cf157a43de27e8d1b84786eb1baabc + d59c983920609fddd0d378921e36388c3bae8d00 diff --git a/eng/Versions.props b/eng/Versions.props index 430797558e14..c51dc9b6be5c 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -69,9 +69,9 @@ <_HarfBuzzSharpVersion>2.8.2.4-preview.82 <_SkiaSharpNativeAssetsVersion>0.0.0-commit.936270ba9372ac6c94505de44884ef4ba5d96aa2.588 7.0.100-preview.5.22226.1 - 8.0.0-prerelease.23312.1 - 8.0.0-prerelease.23312.1 - 8.0.0-prerelease.23312.1 + 8.0.0-prerelease.23321.2 + 8.0.0-prerelease.23321.2 + 8.0.0-prerelease.23321.2 0.9.0 0.5.13 1.2.0 @@ -84,7 +84,7 @@ $(DotNetVersionBand) $(DotNetVersionBand) $(DotNetVersionBand) - $(DotNetVersionBand) - $(DotNetVersionBand) + 8.0.100-preview.6 + 8.0.100-preview.6 diff --git a/eng/devices/catalyst.cake b/eng/devices/catalyst.cake index ca71b904ee7a..c684f22d3a97 100644 --- a/eng/devices/catalyst.cake +++ b/eng/devices/catalyst.cake @@ -4,7 +4,7 @@ string TARGET = Argument("target", "Test"); const string defaultVersion = "14.4"; -const string dotnetVersion = "net7.0"; +const string dotnetVersion = "net8.0"; // required FilePath PROJECT = Argument("project", EnvironmentVariable("MAC_TEST_PROJECT") ?? ""); diff --git a/eng/devices/windows.cake b/eng/devices/windows.cake index e03d96a7f4f1..d81b723cace3 100644 --- a/eng/devices/windows.cake +++ b/eng/devices/windows.cake @@ -4,7 +4,7 @@ string TARGET = Argument("target", "Test"); const string defaultVersion = "10.0.19041"; -const string dotnetVersion = "net7.0"; +const string dotnetVersion = "net8.0"; // required FilePath PROJECT = Argument("project", EnvironmentVariable("WINDOWS_TEST_PROJECT") ?? ""); diff --git a/eng/pipelines/common/ui-tests.yml b/eng/pipelines/common/ui-tests.yml index 6207766dce86..0a206145abd0 100644 --- a/eng/pipelines/common/ui-tests.yml +++ b/eng/pipelines/common/ui-tests.yml @@ -9,6 +9,7 @@ parameters: iosVersions: [ 'latest' ] provisionatorChannel: 'latest' agentPoolAccessToken: '' + runCompatibilityTests: false projects: - name: name desc: Human Description @@ -64,6 +65,7 @@ stages: - ${{ each version in parameters.iosVersions }}: - ${{ if not(containsValue(project.iosVersionsExclude, version)) }}: - job: ios_ui_tests_${{ project.name }}_${{ replace(version, '.', '_') }} + timeoutInMinutes: 120 # how long to run the job before automatically cancelling workspace: clean: all displayName: ${{ coalesce(project.desc, project.name) }} (v${{ version }}) @@ -94,6 +96,7 @@ stages: - ${{ each project in parameters.projects }}: - ${{ if ne(project.winui, '') }}: - job: winui_ui_tests_${{ project.name }} + timeoutInMinutes: 120 # how long to run the job before automatically cancelling workspace: clean: all displayName: ${{ coalesce(project.desc, project.name) }} @@ -116,6 +119,7 @@ stages: - ${{ each project in parameters.projects }}: - ${{ if ne(project.mac, '') }}: - job: mac_ui_tests_${{ project.name }} + timeoutInMinutes: 120 # how long to run the job before automatically cancelling workspace: clean: all displayName: ${{ coalesce(project.desc, project.name) }} @@ -133,72 +137,74 @@ stages: provisionatorChannel: ${{ parameters.provisionatorChannel }} agentPoolAccessToken: ${{ parameters.agentPoolAccessToken }} - - stage: android_compatibility_ui_tests - displayName: Android Compatibility UITests - dependsOn: [] - jobs: - - ${{ each project in parameters.projects }}: - - ${{ if ne(project.android, '') }}: - - ${{ each api in parameters.androidApiLevels }}: - - ${{ if not(containsValue(project.androidApiLevelsExclude, api)) }}: - - job: android_compatibility_ui_tests_${{ project.name }}_${{ api }} - timeoutInMinutes: 240 - workspace: - clean: all - displayName: ${{ coalesce(project.desc, project.name) }} (API ${{ api }}) - pool: ${{ parameters.androidCompatibilityPool }} - variables: - ${{ if ge(api, 24) }}: - ANDROID_EMULATORS: "system-images;android-${{ api }};google_apis_playstore;x86" - ${{ if lt(api, 24) }}: - ANDROID_EMULATORS: "system-images;android-${{ api }};google_apis;x86" - REQUIRED_XCODE: $(DEVICETESTS_REQUIRED_XCODE) - steps: - - template: ui-tests-compatibility-steps.yml - parameters: - platform: android - provisionPlatform: macos - configuration: Debug - version: ${{ api }} - path: ${{ project.compatibilityAndroidTestProject }} - app: ${{ project.compatibilityAndroidApp }} - targetSample: "dotnet-legacy-controlgallery-android" - device: android-emulator-32_${{ api }} - provisionatorChannel: ${{ parameters.provisionatorChannel }} - agentPoolAccessToken: ${{ parameters.agentPoolAccessToken }} + - ${{ if eq(parameters.runCompatibilityTests, true) }}: + - stage: android_compatibility_ui_tests + displayName: Android Compatibility UITests + dependsOn: [] + jobs: + - ${{ each project in parameters.projects }}: + - ${{ if ne(project.android, '') }}: + - ${{ each api in parameters.androidApiLevels }}: + - ${{ if not(containsValue(project.androidApiLevelsExclude, api)) }}: + - job: android_compatibility_ui_tests_${{ project.name }}_${{ api }} + timeoutInMinutes: 240 + workspace: + clean: all + displayName: ${{ coalesce(project.desc, project.name) }} (API ${{ api }}) + pool: ${{ parameters.androidCompatibilityPool }} + variables: + ${{ if ge(api, 24) }}: + ANDROID_EMULATORS: "system-images;android-${{ api }};google_apis_playstore;x86" + ${{ if lt(api, 24) }}: + ANDROID_EMULATORS: "system-images;android-${{ api }};google_apis;x86" + REQUIRED_XCODE: $(DEVICETESTS_REQUIRED_XCODE) + steps: + - template: ui-tests-compatibility-steps.yml + parameters: + platform: android + provisionPlatform: macos + configuration: Debug + version: ${{ api }} + path: ${{ project.compatibilityAndroidTestProject }} + app: ${{ project.compatibilityAndroidApp }} + targetSample: "dotnet-legacy-controlgallery-android" + device: android-emulator-32_${{ api }} + provisionatorChannel: ${{ parameters.provisionatorChannel }} + agentPoolAccessToken: ${{ parameters.agentPoolAccessToken }} - - stage: ios_compatibility_ui_tests - displayName: iOS Compatibility UITests - dependsOn: [] - jobs: - - ${{ each project in parameters.projects }}: - - ${{ if ne(project.ios, '') }}: - - ${{ each version in parameters.iosVersions }}: - - ${{ if not(containsValue(project.iosVersionsExclude, version)) }}: - - job: ios_compatibility_ui_tests_${{ project.name }}_${{ replace(version, '.', '_') }} - timeoutInMinutes: 240 - workspace: - clean: all - displayName: ${{ coalesce(project.desc, project.name) }} (v${{ version }}) - pool: ${{ parameters.iosCompatibilityPool }} - variables: - REQUIRED_XCODE: $(DEVICETESTS_REQUIRED_XCODE) - steps: - - template: ui-tests-compatibility-steps.yml - parameters: - platform: ios - provisionPlatform: macos - configuration: Debug - ${{ if eq(version, 'latest') }}: - version: 16.2 - ${{ if ne(version, 'latest') }}: - version: ${{ version }} - path: ${{ project.compatibilityiOSTestProject }} - app: ${{ project.compatibilityiOSApp }} - targetSample: "dotnet-legacy-controlgallery-ios" - ${{ if eq(version, 'latest') }}: - device: ios-simulator-64 - ${{ if ne(version, 'latest') }}: - device: ios-simulator-64_${{ version }} - provisionatorChannel: ${{ parameters.provisionatorChannel }} - agentPoolAccessToken: ${{ parameters.agentPoolAccessToken }} + + - stage: ios_compatibility_ui_tests + displayName: iOS Compatibility UITests + dependsOn: [] + jobs: + - ${{ each project in parameters.projects }}: + - ${{ if ne(project.ios, '') }}: + - ${{ each version in parameters.iosVersions }}: + - ${{ if not(containsValue(project.iosVersionsExclude, version)) }}: + - job: ios_compatibility_ui_tests_${{ project.name }}_${{ replace(version, '.', '_') }} + timeoutInMinutes: 240 + workspace: + clean: all + displayName: ${{ coalesce(project.desc, project.name) }} (v${{ version }}) + pool: ${{ parameters.iosCompatibilityPool }} + variables: + REQUIRED_XCODE: $(DEVICETESTS_REQUIRED_XCODE) + steps: + - template: ui-tests-compatibility-steps.yml + parameters: + platform: ios + provisionPlatform: macos + configuration: Debug + ${{ if eq(version, 'latest') }}: + version: 16.2 + ${{ if ne(version, 'latest') }}: + version: ${{ version }} + path: ${{ project.compatibilityiOSTestProject }} + app: ${{ project.compatibilityiOSApp }} + targetSample: "dotnet-legacy-controlgallery-ios" + ${{ if eq(version, 'latest') }}: + device: ios-simulator-64 + ${{ if ne(version, 'latest') }}: + device: ios-simulator-64_${{ version }} + provisionatorChannel: ${{ parameters.provisionatorChannel }} + agentPoolAccessToken: ${{ parameters.agentPoolAccessToken }} diff --git a/eng/pipelines/ui-tests.yml b/eng/pipelines/ui-tests.yml index 7dfe455b79d4..1268d194e616 100644 --- a/eng/pipelines/ui-tests.yml +++ b/eng/pipelines/ui-tests.yml @@ -57,6 +57,10 @@ parameters: type: boolean default: false + - name: CompatibilityTests + type: boolean + default: false + - name: androidPool type: object default: @@ -135,23 +139,9 @@ stages: # androidApiLevels: [ 30, 21 ] # fix the issue of getting the test results off iosVersions: [ 'latest' ] provisionatorChannel: ${{ parameters.provisionatorChannel }} + ${{ if or(parameters.CompatibilityTests, ne(variables['Build.Reason'], 'PullRequest')) }}: + runCompatibilityTests: true projects: - # - name: essentials - # desc: Essentials - # androidApiLevelsExclude: [25] # Ignore for now API25 since the runs's are not stable - # android: $(System.DefaultWorkingDirectory)/src/Essentials/test/DeviceTests/Essentials.DeviceTests.csproj - # ios: $(System.DefaultWorkingDirectory)/src/Essentials/test/DeviceTests/Essentials.DeviceTests.csproj - # - name: graphics - # desc: Graphics - # androidApiLevelsExclude: [25] # Ignore for now API25 since the runs's are not stable - # android: $(System.DefaultWorkingDirectory)/src/Graphics/tests/DeviceTests/Graphics.DeviceTests.csproj - # ios: $(System.DefaultWorkingDirectory)/src/Graphics/tests/DeviceTests/Graphics.DeviceTests.csproj - # - name: core - # desc: Core - # androidApiLevelsExclude: [25] # Ignore for now API25 since the runs's are not stable - # android: $(System.DefaultWorkingDirectory)/src/Core/tests/DeviceTests/Core.DeviceTests.csproj - # iosVersionsExclude: [ '12.4'] # Ignore iOS 12.4 while we can't make it work on CI - # ios: $(System.DefaultWorkingDirectory)/src/Core/tests/DeviceTests/Core.DeviceTests.csproj - name: controls desc: Controls androidApiLevelsExclude: [25] # Ignore for now API25 since the runs's are not stable @@ -165,10 +155,4 @@ stages: compatibilityAndroidTestProject: $(System.DefaultWorkingDirectory)/src/Compatibility/ControlGallery/test/Android.UITests/Compatibility.ControlGallery.Android.UITests.csproj compatibilityiOSApp: $(System.DefaultWorkingDirectory)/src/Compatibility/ControlGallery/src/iOS/Compatibility.ControlGallery.iOS.csproj compatibilityiOSTestProject: $(System.DefaultWorkingDirectory)/src/Compatibility/ControlGallery/test/iOS.UITests/Compatibility.ControlGallery.iOS.UITests.csproj - # - name: blazorwebview - # desc: BlazorWebView - # androidApiLevelsExclude: [ 27, 26, 25, 24, 23, 22, 21 ] # BlazorWebView requires a recent version of Chrome - # android: $(System.DefaultWorkingDirectory)/src/BlazorWebView/tests/MauiDeviceTests/MauiBlazorWebView.DeviceTests.csproj - # iosVersionsExclude: [ '12.4'] # Ignore iOS 12.4 while we can't make it work on CI - # ios: $(System.DefaultWorkingDirectory)/src/BlazorWebView/tests/MauiDeviceTests/MauiBlazorWebView.DeviceTests.csproj diff --git a/src/Compatibility/ControlGallery/src/Issues.Shared/Bugzilla31366.cs b/src/Compatibility/ControlGallery/src/Issues.Shared/Bugzilla31366.cs index 1902e13f04d3..af27d1d8b71b 100644 --- a/src/Compatibility/ControlGallery/src/Issues.Shared/Bugzilla31366.cs +++ b/src/Compatibility/ControlGallery/src/Issues.Shared/Bugzilla31366.cs @@ -78,6 +78,7 @@ protected override void Init() #if UITEST [Test] [UiTest(typeof(NavigationPage))] + [Compatibility.UITests.FailsOnMauiIOS] public void Issue31366PushingAndPoppingModallyCausesArgumentOutOfRangeException() { RunningApp.Tap(q => q.Marked("Start PopOnAppearing Test")); @@ -86,6 +87,7 @@ public void Issue31366PushingAndPoppingModallyCausesArgumentOutOfRangeException( [Test] [UiTest(typeof(NavigationPage))] + [Compatibility.UITests.FailsOnMauiIOS] public void Issue31366PushingWithModalStackCausesIncorrectStackOrder() { RunningApp.Tap(q => q.Marked("Start ModalStack Test")); diff --git a/src/Compatibility/ControlGallery/src/Issues.Shared/Issue1975.cs b/src/Compatibility/ControlGallery/src/Issues.Shared/Issue1975.cs index 69a4e7ba5aae..e453156c99be 100644 --- a/src/Compatibility/ControlGallery/src/Issues.Shared/Issue1975.cs +++ b/src/Compatibility/ControlGallery/src/Issues.Shared/Issue1975.cs @@ -142,6 +142,8 @@ public SubItem(string text) #if UITEST [Test] + [Compatibility.UITests.FailsOnMauiIOS] + [Compatibility.UITests.FailsOnMauiAndroid] public void UpdatingSourceOfDisposedListViewDoesNotCrash() { RunningApp.Tap(Go); diff --git a/src/Compatibility/ControlGallery/src/Issues.Shared/Issue4597.cs b/src/Compatibility/ControlGallery/src/Issues.Shared/Issue4597.cs index ab8bc9d4c019..d4b4716378b1 100644 --- a/src/Compatibility/ControlGallery/src/Issues.Shared/Issue4597.cs +++ b/src/Compatibility/ControlGallery/src/Issues.Shared/Issue4597.cs @@ -194,6 +194,7 @@ public void ImageFromUriSourceAppearsAndDisappearsCorrectly() [Test] [Compatibility.UITests.FailsOnMauiIOS] + [Compatibility.UITests.FailsOnMauiAndroid] public void ButtonFromFileSourceAppearsAndDisappearsCorrectly() { RunTest(nameof(Button), true); @@ -202,6 +203,7 @@ public void ButtonFromFileSourceAppearsAndDisappearsCorrectly() [Test] [NUnit.Framework.Category(UITestCategories.RequiresInternetConnection)] [Compatibility.UITests.FailsOnMauiIOS] + [Compatibility.UITests.FailsOnMauiAndroid] public void ButtonFromUriSourceAppearsAndDisappearsCorrectly() { RunTest(nameof(Button), false); @@ -210,7 +212,7 @@ public void ButtonFromUriSourceAppearsAndDisappearsCorrectly() [Test] [Compatibility.UITests.FailsOnMauiIOS] - [FailsOnMauiAndroid] + [Compatibility.UITests.FailsOnMauiAndroid] public void ImageButtonFromFileSourceAppearsAndDisappearsCorrectly() { RunTest(nameof(ImageButton), true); @@ -218,7 +220,7 @@ public void ImageButtonFromFileSourceAppearsAndDisappearsCorrectly() [Test] [Compatibility.UITests.FailsOnMauiIOS] - [FailsOnMauiAndroid] + [Compatibility.UITests.FailsOnMauiAndroid] [NUnit.Framework.Category(UITestCategories.RequiresInternetConnection)] public void ImageButtonFromUriSourceAppearsAndDisappearsCorrectly() { @@ -227,14 +229,15 @@ public void ImageButtonFromUriSourceAppearsAndDisappearsCorrectly() [Test] [Compatibility.UITests.FailsOnMauiIOS] + [Compatibility.UITests.FailsOnMauiAndroid] public void ImageCellFromFileSourceAppearsAndDisappearsCorrectly() { ImageCellTest(true); } [Test] - [Microsoft.Maui.Controls.Compatibility.UITests.FailsOnMauiAndroid] - [NUnit.Framework.Category(UITestCategories.RequiresInternetConnection)] + [Compatibility.UITests.FailsOnMauiIOS] + [Compatibility.UITests.FailsOnMauiAndroid] public void ImageCellFromUriSourceAppearsAndDisappearsCorrectly() { ImageCellTest(false); diff --git a/src/Compatibility/ControlGallery/src/Issues.Shared/SwipeBackNavCrash.cs b/src/Compatibility/ControlGallery/src/Issues.Shared/SwipeBackNavCrash.cs index 485985d30be0..6f006c353846 100644 --- a/src/Compatibility/ControlGallery/src/Issues.Shared/SwipeBackNavCrash.cs +++ b/src/Compatibility/ControlGallery/src/Issues.Shared/SwipeBackNavCrash.cs @@ -31,6 +31,7 @@ protected override void Init() #if UITEST [Test] + [Compatibility.UITests.FailsOnMauiIOS] public void SwipeBackNavCrashTestsAllElementsPresent () { RunningApp.WaitForElement (q => q.Marked ("Page One")); @@ -38,6 +39,7 @@ public void SwipeBackNavCrashTestsAllElementsPresent () } [Test] + [Compatibility.UITests.FailsOnMauiIOS] public void SwipeBackNavCrashTestsGoToSecondPage () { RunningApp.WaitForElement (q => q.Marked ("Page One")); @@ -47,6 +49,7 @@ public void SwipeBackNavCrashTestsGoToSecondPage () #if __IOS__ [Test] + [Compatibility.UITests.FailsOnMauiIOS] public void SwipeBackNavCrashTestsSwipeBackDoesNotCrash () { RunningApp.WaitForElement (q => q.Marked ("Page One")); diff --git a/src/Compatibility/ControlGallery/src/Issues.Shared/TabbedPageTests.cs b/src/Compatibility/ControlGallery/src/Issues.Shared/TabbedPageTests.cs index 559380df471d..f53274c11ecb 100644 --- a/src/Compatibility/ControlGallery/src/Issues.Shared/TabbedPageTests.cs +++ b/src/Compatibility/ControlGallery/src/Issues.Shared/TabbedPageTests.cs @@ -36,6 +36,7 @@ protected override void Init() #if UITEST [Test] + [Compatibility.UITests.FailsOnMauiIOS] public void TabbedPageWithModalIssueTestsAllElementsPresent () { RunningApp.WaitForElement (q => q.Marked ("Page 1")); @@ -46,6 +47,7 @@ public void TabbedPageWithModalIssueTestsAllElementsPresent () } [Test] + [Compatibility.UITests.FailsOnMauiIOS] public void TabbedPageWithModalIssueTestsPopFromFirstTab () { RunningApp.Tap (q => q.Button ("Pop")); @@ -55,6 +57,7 @@ public void TabbedPageWithModalIssueTestsPopFromFirstTab () } [Test] + [Compatibility.UITests.FailsOnMauiIOS] public void TabbedPageWithModalIssueTestsPopFromSecondTab () { RunningApp.Tap (q => q.Marked ("Page 2")); diff --git a/src/Compatibility/ControlGallery/src/Issues.Shared/TabbedPageWithList.cs b/src/Compatibility/ControlGallery/src/Issues.Shared/TabbedPageWithList.cs index 2d9fa94afa2d..31b2c5b5014d 100644 --- a/src/Compatibility/ControlGallery/src/Issues.Shared/TabbedPageWithList.cs +++ b/src/Compatibility/ControlGallery/src/Issues.Shared/TabbedPageWithList.cs @@ -31,6 +31,7 @@ protected override void Init() #if UITEST [Test] + [Compatibility.UITests.FailsOnMauiIOS] public void TabbedPageWithListViewIssueTestsAllElementsPresent () { RunningApp.WaitForElement (q => q.Marked ("Tab Two")); @@ -39,6 +40,7 @@ public void TabbedPageWithListViewIssueTestsAllElementsPresent () } [Test] + [Compatibility.UITests.FailsOnMauiIOS] public void TabbedPageWithListViewIssueTestsNavigateToAndVerifyListView () { RunningApp.Tap (q => q.Marked ("List Page")); diff --git a/src/Controls/samples/Controls.Sample/Pages/Core/PointerGestureGalleryPage.xaml b/src/Controls/samples/Controls.Sample/Pages/Core/PointerGestureGalleryPage.xaml index a32c8c54bf26..627b155c34eb 100644 --- a/src/Controls/samples/Controls.Sample/Pages/Core/PointerGestureGalleryPage.xaml +++ b/src/Controls/samples/Controls.Sample/Pages/Core/PointerGestureGalleryPage.xaml @@ -16,5 +16,8 @@