.NET MAUI中XAML Hot Reload自定义控件更新异常问题
.NET MAUI自定义控件XAML Hot Reload失效问题
我体验.NET MAUI已有数日,该框架取消了XAML设计器,开发应用GUI时完全依赖XAML Hot Reload功能,但实测该功能对自定义控件无法正常生效。
本次问题复现所用的演示控件参考自微软官方文档的ContentView示例,我以.NET MAUI默认项目模板为基础实现了该示例控件,随后复现了异常行为。
测试环境
- Visual Studio 2022 (17.3.0 Preview 1.1)
- Visual Studio 2022 (17.3.0 Preview 2.0)
复现场景
场景1
首次启动应用时,MainPage.xaml中未定义CardView实例。此时修改项目模板生成的MainPage.xaml样板代码可正常触发GUI刷新,例如修改Label控件的文本(将"Hello, World!"修改为"Hello, Maui!"),可通过Hot Reload功能正常更新标签显示内容。
该场景下向MainPage.xaml中新增CardView实例,可通过Hot Reload正常创建对应UI元素并更新GUI;修改官方文档中提及的CardTitle、CardDescription等可绑定属性也符合预期,GUI可通过Hot Reload同步更新。
场景2
该场景承接场景1:完成上述新增、编辑CardView的操作后关闭应用,重新启动实时调试器时,之前已添加的CardView在修改后无法再通过Hot Reload触发更新;但新增CardView元素仍可按场景1的预期正常工作,Label等内置核心控件不受该问题影响。
问题结论
应用启动时已存在于XAML视觉树中的自定义控件,无法通过Hot Reload功能响应修改更新。
待确认问题
- 是否遗漏了该功能正常运行的必要配置?
- 是否需要在
csproj文件中添加特定属性或配置项? - 是否需要为自定义控件实现特定接口才能让Hot Reload正常工作?
- 该问题是否属于当前预览版本的已知Bug?
复现代码
MauiProject.csproj
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net6.0-windows10.0.19041.0</TargetFrameworks> <OutputType>Exe</OutputType> <RootNamespace>MauiProject</RootNamespace> <UseMaui>true</UseMaui> <SingleProject>true</SingleProject> <ImplicitUsings>enable</ImplicitUsings> <!-- Display name --> <ApplicationTitle>MauiProject</ApplicationTitle> <!-- App Identifier --> <ApplicationId>com.example.mauiproject</ApplicationId> <ApplicationIdGuid>2357E05B-5E8B-45AE-8942-76AD07490831</ApplicationIdGuid> <!-- Versions --> <ApplicationDisplayVersion>1.0</ApplicationDisplayVersion> <ApplicationVersion>1</ApplicationVersion> <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</SupportedOSPlatformVersion> <TargetPlatformMinVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</TargetPlatformMinVersion> <Platforms>AnyCPU;x64</Platforms> <XamlDebuggingInformation>True</XamlDebuggingInformation> <DisableXbfLineInfo>False</DisableXbfLineInfo> </PropertyGroup> <ItemGroup> <!-- App Icon --> <MauiIcon Include="Resources\appicon.svg" ForegroundFile="Resources\appiconfg.svg" Color="#512BD4" /> <!-- Splash Screen --> <MauiSplashScreen Include="Resources\appiconfg.svg" Color="#512BD4" BaseSize="128,128" /> <!-- Images --> <MauiImage Include="Resources\Images\*" /> <MauiImage Update="Resources\Images\dotnet_bot.svg" BaseSize="168,208" /> <!-- Custom Fonts --> <MauiFont Include="Resources\Fonts\*" /> <!-- Raw Assets (also remove the "Resources\Raw" prefix) --> <MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" /> </ItemGroup> <ItemGroup> <Compile Update="CardView.xaml.cs"> <DependentUpon>%(Filename)</DependentUpon> </Compile> </ItemGroup> <ItemGroup> <MauiXaml Update="CardView.xaml"> <Generator>MSBuild:Compile</Generator> </MauiXaml> </ItemGroup> </Project>
MainPage.xaml
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:MauiProject" x:Class="MauiProject.MainPage"> <ScrollView> <HorizontalStackLayout Spacing="25" Padding="0"> <VerticalStackLayout Spacing="25" Padding="30,0" VerticalOptions="Center"> <local:CardView HeightRequest="150" CardTitle="Pre-existing card" CardDescription="This cards already exists in the visual tree when the app is started"> </local:CardView> <!--<local:CardView HeightRequest="150" CardTitle="Added card" CardDescription="This card is commented out and can be added at runtime by uncommenting"> </local:CardView>--> <Image Source="dotnet_bot.png" SemanticProperties.Description="Cute dot net bot waving hi to you!" HeightRequest="200" HorizontalOptions="Center" /> <Label Text="Hello, World!" SemanticProperties.HeadingLevel="Level1" FontSize="48" HorizontalOptions="Center" /> <Label Text="Welcome to .NET Multi-platform App UI" SemanticProperties.HeadingLevel="Level2" SemanticProperties.Description="Welcome to dot net Multi platform App U I" FontSize="18" HorizontalOptions="Center" /> <Button x:Name="CounterBtn" Text="Click me" SemanticProperties.Hint="Counts the number of times you click" Clicked="OnCounterClicked" HorizontalOptions="Center" /> </VerticalStackLayout> </HorizontalStackLayout> </ScrollView> </ContentPage>
CardView.xaml
<?xml version="1.0" encoding="utf-8" ?> <ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Name="this" x:Class="MauiProject.CardView"> <Frame BindingContext="{x:Reference this}" BackgroundColor="{Binding CardColor}" BorderColor="{Binding BorderColor}"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="21"/> <RowDefinition Height="84"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="80"/> <ColumnDefinition Width="120"/> </Grid.ColumnDefinitions> <Frame BorderColor="{Binding BorderColor, FallbackValue='Black'}" BackgroundColor="{Binding BackgroundColor, FallbackValue='Transparent'}" Margin="12" Grid.Row="0" Grid.RowSpan="2" Grid.Column="0"> <Image Source="{Binding IconImageSource}" /> </Frame> <Label Text="{Binding CardTitle, FallbackValue='Card Title'}" Grid.Row="0" Grid.Column="1" FontAttributes="Bold"></Label> <Label Text="{Binding CardDescription, FallbackValue='Card description text'}" Grid.Row="1" Grid.Column="1" /> </Grid> </Frame> </ContentView>
CardView.xaml.cs
namespace MauiProject; public partial class CardView : ContentView { public static readonly BindableProperty CardTitleProperty = BindableProperty.Create(nameof(CardTitle), typeof(string), typeof(CardView), string.Empty); public string CardTitle { get => (string)GetValue(CardView.CardTitleProperty); set => SetValue(CardView.CardTitleProperty, value); } public static readonly BindableProperty CardDescriptionProperty = BindableProperty.Create(nameof(CardDescription), typeof(string), typeof(CardView), string.Empty); public string CardDescription { get => (string)GetValue(CardView.CardDescriptionProperty); set => SetValue(CardView.CardDescriptionProperty, value); } public static readonly BindableProperty IconImageSourceProperty = BindableProperty.Create(nameof(IconImageSource), typeof(ImageSource), typeof(CardView), null); public ImageSource IconImageSource { get { return (ImageSource)GetValue(CardView.IconImageSourceProperty); } set { SetValue(CardView.IconImageSourceProperty, value); } } public static readonly BindableProperty IconImageBackgroundProperty = BindableProperty.Create(nameof(IconImageBackground), typeof(Color), typeof(CardView), Colors.Transparent); public Color IconImageBackground { get { return (Color)GetValue(CardView.IconImageBackgroundProperty); } set { SetValue(CardView.IconImageBackgroundProperty, value); } } public static readonly BindableProperty CardColorProperty = BindableProperty.Create(nameof(CardColor), typeof(Color), typeof(CardView), Colors.Gray); public Color CardColor { get { return (Color)GetValue(CardView.CardColorProperty); } set { SetValue(CardView.CardColorProperty, value); } } public static readonly BindableProperty BorderColorProperty = BindableProperty.Create(nameof(BorderColor), typeof(Color), typeof(CardView), Colors.Black); public Color BorderColor { get { return (Color)GetValue(CardView.BorderColorProperty); } set { SetValue(CardView.BorderColorProperty, value); } } public CardView() { InitializeComponent(); } }
内容的提问来源于stack exchange,提问作者walkslowly
相关产品推荐
相关产品推荐

