【问题标题】:C# Community Toolkit Mvvm Source Generator: ObservableProperty capitalises property nameC# Community Toolkit Mvvm Source Generator:ObservableProperty 大写属性名称
【发布时间】:2023-01-20 19:03:07
【问题描述】:

我刚刚开始使用该工具包,我正在尝试生成一个简单的 ObservableProperty 以与 WPF 一起使用。我创建了一个用户控件:

<UserControl x:Class="WPF_test.StatusControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:WPF_test"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <TextBox x:Name="txtTest" Text="{Binding testData}" Grid.Column="0" Grid.Row="0" Margin="5,5,5,5" />
    </Grid>
</UserControl>

和一个视图模型:

using System;
using CommunityToolkit.Mvvm;
using CommunityToolkit.Mvvm.ComponentModel;

namespace WPF_test
{
    [ObservableObject]
    public partial class StatusControlViewModel
    {
        [ObservableProperty]
        private String? testData;
    }
}

我将控件嵌入到 MainWindow 中并在代码隐藏中设置数据上下文:

    public partial class MainWindow : Window
    {
        StatusControlViewModel model;
        public MainWindow()
        {
            InitializeComponent();
            model = new StatusControlViewModel();
            status.DataContext = model;
            model.testData = "test";
        }
    }

但我看到 model.testData 由于其保护级别而无法访问。当我注释掉这一行以使代码运行时,我收到一个绑定错误,指出无法找到 testData。

这是生成的代码:

namespace WPF_test
{
    partial class StatusControlViewModel
    {
        /// <inheritdoc cref="testData"/>
        [global::System.CodeDom.Compiler.GeneratedCode("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator", "8.0.0.0")]
        [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
        public string? TestData
        {
            get => testData;
            set
            {
                if (!global::System.Collections.Generic.EqualityComparer<string?>.Default.Equals(testData, value))
                {
                    OnTestDataChanging(value);
                    OnPropertyChanging(global::CommunityToolkit.Mvvm.ComponentModel.__Internals.__KnownINotifyPropertyChangingArgs.TestData);
                    testData = value;
                    OnTestDataChanged(value);
                    OnPropertyChanged(global::CommunityToolkit.Mvvm.ComponentModel.__Internals.__KnownINotifyPropertyChangedArgs.TestData);
                }
            }
        }

        /// <summary>Executes the logic for when <see cref="TestData"/> is changing.</summary>
        [global::System.CodeDom.Compiler.GeneratedCode("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator", "8.0.0.0")]
        partial void OnTestDataChanging(string? value);
        /// <summary>Executes the logic for when <see cref="TestData"/> just changed.</summary>
        [global::System.CodeDom.Compiler.GeneratedCode("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator", "8.0.0.0")]
        partial void OnTestDataChanged(string? value);
    }
}

看来该工具包正在大写我的财产名称。我可以通过将控件 XAML 中的属性名称大写来进行数据绑定:

<TextBox x:Name="txtTest" Text="{Binding TestData}" Grid.Column="0" Grid.Row="0" Margin="5,5,5,5" />

并类似地访问模型属性:

model.TestData = "test";

有没有办法使用工具包,以便以原始形式访问属性,即

<TextBox x:Name="txtTest" Text="{Binding testData}" Grid.Column="0" Grid.Row="0" Margin="5,5,5,5" />

不是

<TextBox x:Name="txtTest" Text="{Binding TestData}" Grid.Column="0" Grid.Row="0" Margin="5,5,5,5" />

?我认为否则会令人困惑。

【问题讨论】:

    标签: c# wpf mvvm


    【解决方案1】:

    不。

    没有办法“使用工具包以便以原始形式访问属性”

    因为那是一个领域而不是一个属性。

    代码生成器实际上是在生成一些代码。

    属性名称不能与您的支持字段相同。 testData 是一个字段。您不能绑定到字段。

        [ObservableProperty]
        private String? testData;
    

    在分部类中生成一个 TestData 属性。

        public string? TestData
        {
            get => testData;
            set
            {
                if (!global::System.Collections.Generic.EqualityComparer<string?>.Default.Equals(testData, value))
                {
                    OnTestDataChanging(value);
                    OnPropertyChanging(global::CommunityToolkit.Mvvm.ComponentModel.__Internals.__KnownINotifyPropertyChangingArgs.TestData);
                    testData = value;
                    OnTestDataChanged(value);
                    OnPropertyChanged(global::CommunityToolkit.Mvvm.ComponentModel.__Internals.__KnownINotifyPropertyChangedArgs.TestData);
                }
            }
        }
    

    您只能绑定到公共属性,因此您需要生成的内容才能绑定。没有财产意味着没有约束力。

    捆绑:

    https://learn.microsoft.com/en-us/dotnet/desktop/wpf/data/?view=netdesktop-6.0

    财产:

    https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/properties

    上面_seconds是一个字段。

    小时是一个属性。

    不同之处在于属性具有 getter 和(可选)setter。

    说了这么多。

    您不必被迫使用该属性。

    您可以手动创建属性。

    然后你可以为你的财产准备任何你喜欢的箱子。

    我建议你学会喜欢大写属性。

    我为很多客户工作过。属性名称的标准始终是以大写字母开头。

    聚苯乙烯

    [Relaycommand] 生成附加了“Command”的上层属性。

    【讨论】:

      猜你喜欢
      • 2023-02-06
      • 2015-12-24
      • 1970-01-01
      • 2022-08-16
      • 2022-12-11
      • 2017-06-24
      • 2011-06-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多