You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET MAUI ContentView属性值及绑定更新异常修复咨询

.NET MAUI ProgressCardView 控件修复方案

问题根源分析

你的控件出现显示异常的核心原因有以下几点:

  • 所有BindableProperty定义错误使用了ProgressCardView2作为所有者类型,实际控件类是ProgressCardView,导致绑定完全失效
  • Score和Percentage是普通属性,未实现属性变化通知,且依赖的私有字段未与Attempted/Possible同步
  • ProgressBar未绑定进度值,无法展示分数对应的进度
  • 未处理分母为0的异常情况

修正后的代码

1. ProgressCardView.xaml(仅修改ProgressBar绑定)

<?xml version="1.0" encoding="utf-8" ?>
<ContentView x:Name="this"
             xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ExampleApp.Controls.ProgressCardView">
    <Frame BindingContext="{x:Reference this}" BackgroundColor="{Binding BackgroundColor}" CornerRadius="5" HasShadow="True">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="3*"   />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="2*"   />
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="10*" />
                <ColumnDefinition Width="4*"  />
                <ColumnDefinition Width="4*"  />
            </Grid.ColumnDefinitions>

            <Button x:Name="InternalButton" Grid.RowSpan="3" Grid.ColumnSpan="2" Opacity="0.0" Clicked="buttonEvent" />

            <Label Text="{Binding Title}" HorizontalOptions="Start" VerticalOptions="Center" FontSize="17" TextColor="{Binding HeaderColor}" />
            <Label Text="{Binding Score}" Grid.Column="1" Grid.ColumnSpan="2" HorizontalOptions="End" VerticalOptions="Center" FontSize="12" TextColor="{Binding TextColor}" />
            <BoxView Grid.Row="1" Grid.ColumnSpan="3" HeightRequest="1" Color="{Binding TextColor}"/>
            <!-- 新增Progress属性绑定 -->
            <ProgressBar x:Name="CardProgressBar" Grid.Row="2" Grid.ColumnSpan="2" Progress="{Binding ProgressValue}" />
            <Label Text="{Binding Percentage}" Grid.Row="2" Grid.Column="2" HorizontalOptions="End" VerticalOptions="Center" FontSize="12" TextColor="{Binding TextColor}" />
        </Grid>
    </Frame>
</ContentView>

2. ProgressCardView.xaml.cs(核心修正)

namespace ExampleApp.Controls
{
    public partial class ProgressCardView : ContentView
    {
        private int _attempted = 0;
        private int _possible = 1;

        #region BindableProperties

        public static readonly BindableProperty TitleProperty = BindableProperty.Create(
            nameof(Title), 
            typeof(string), 
            typeof(ProgressCardView), // 修正为正确的控件类名
            string.Empty);

        public static readonly BindableProperty AttemptedProperty = BindableProperty.Create(
            nameof(Attempted),
            typeof(int),
            typeof(ProgressCardView), // 修正为正确的控件类名
            0,
            propertyChanged: OnAttemptedOrPossibleChanged); // 添加属性变化回调

        public static readonly BindableProperty PossibleProperty = BindableProperty.Create(
            nameof(Possible),
            typeof(int),
            typeof(ProgressCardView), // 修正为正确的控件类名
            1,
            propertyChanged: OnAttemptedOrPossibleChanged); // 添加属性变化回调

        public static readonly BindableProperty BackgroundColorProperty = BindableProperty.Create(
            nameof(BackgroundColor), 
            typeof(Color), 
            typeof(ProgressCardView), // 修正为正确的控件类名
            Color.FromArgb("#FFFFFF"));

        public static readonly BindableProperty HeaderColorProperty = BindableProperty.Create(
            nameof(HeaderColor), 
            typeof(Color), 
            typeof(ProgressCardView), // 修正为正确的控件类名
            Color.FromArgb("#FFFFFF"));

        public static readonly BindableProperty TextColorProperty = BindableProperty.Create(
            nameof(TextColor), 
            typeof(Color), 
            typeof(ProgressCardView), // 修正为正确的控件类名
            Color.FromArgb("#FFFFFF"));

        #endregion

        #region Properties

        public string Title 
        {
            get => (string)GetValue(TitleProperty);
            set => SetValue(TitleProperty, value);
        }

        public int Attempted
        {
            get => _attempted;
            set => SetValue(AttemptedProperty, value);
        }

        public int Possible
        {
            get => _possible;
            set => SetValue(PossibleProperty, value);
        }

        // 计算属性,自动同步Attempted/Possible变化
        public string Score
        {
            get => $"{_attempted}/{_possible}";
        }

        public string Percentage
        {
            get 
            {
                if (_possible == 0) return "0.0%"; // 避免除以0异常
                return $"{((double)_attempted / _possible):P1}"; 
            }
        }

        // 进度条绑定值
        public double ProgressValue
        {
            get 
            {
                if (_possible == 0) return 0;
                return (double)_attempted / _possible; 
            }
        }

        public Color BackgroundColor
        {
            get => (Color)GetValue(BackgroundColorProperty);
            set => SetValue(BackgroundColorProperty, value);
        }

        public Color HeaderColor
        {
            get => (Color)GetValue(HeaderColorProperty);
            set => SetValue(HeaderColorProperty, value);
        }

        public Color TextColor
        {
            get => (Color)GetValue(TextColorProperty);
            set => SetValue(TextColorProperty, value);
        }

        #endregion

        #region Methods and Events

        public ProgressCardView()
        {
            InitializeComponent();
        }

        // 属性变化时更新计算属性的UI绑定
        private static void OnAttemptedOrPossibleChanged(BindableObject bindable, object oldValue, object newValue)
        {
            if (bindable is not ProgressCardView card) return;
            
            // 同步私有字段
            card._attempted = (int)bindable.GetValue(AttemptedProperty);
            card._possible = Math.Max(1, (int)bindable.GetValue(PossibleProperty)); // 确保分母不为0

            // 通知UI更新计算属性
            card.OnPropertyChanged(nameof(Score));
            card.OnPropertyChanged(nameof(Percentage));
            card.OnPropertyChanged(nameof(ProgressValue));
        }

        private void buttonEvent(object sender, EventArgs e)
        {
            // 在此添加卡片点击逻辑
        }

        #endregion
    }
}

关键修改说明

  1. 修正BindableProperty所有者类型:所有绑定属性的第三个参数改为当前控件类ProgressCardView,解决绑定失效问题
  2. 添加属性变化回调:当Attempted或Possible值变化时,自动同步私有字段并通知计算属性更新
  3. 实现计算属性通知:通过OnPropertyChanged触发UI刷新,确保Score、Percentage、ProgressValue实时更新
  4. 异常防护:处理Possible为0的情况,避免运行时除以0错误
  5. 进度条绑定:给ProgressBar添加Progress属性绑定,展示分数对应的进度

内容的提问来源于stack exchange,提问作者ecfedele

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 10:25:18