【问题标题】:Get the property value set in the Designer from another property of a Custom Control从自定义控件的另一个属性中获取设计器中设置的属性值
【发布时间】:2020-09-12 18:38:38
【问题描述】:

我制作了自定义控件并添加了一个新属性,该属性旨在指向一个资源。
如何从自定义控件的另一个属性中获取在表单设计器中设置的该属性的值? 当我尝试读取它时,它返回的值是null

我的代码与自定义控件和提到的属性相关:

class ResourceLabel : Label
{
    private string resourceKey;
    
    [Category("Appearance")]
    [Browsable(true)]
    [Description("Sets the resource key for localization")]
    public string ResourceKey
    {
        get { return resourceKey; }
        set {
            if (resourceKey != value) {
                resourceKey = value;
                Invalidate();
            }
        }
    }

    [Browsable(true)]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
    [EditorBrowsable(EditorBrowsableState.Always)]
    [Bindable(true)]
    public override string Text
    {
        if (base.Text != value) {
            Console.WriteLine($"Test: {ResourceKey}");

            if (ResourceKey != null) {
                var locale = CultureInfo.GetCultureInfo(Properties.Settings.Default.Language);
                var textFromResource = Resources.ResourceManager.GetString(ResourceKey, locale);
                base.Text = textFromResource;
            } 
            else {
                base.Text = value;
            }
        }
    }
}

这个字符串Console.WriteLine($"Test: {ResourceKey}"); 返回null

【问题讨论】:

  • Hans 的建议很有趣,但这里的重点(至少我要说明的一点)是,你很可能不需要这个财产。当您使用 Localizable Designer 属性本地化您的应用程序时,将为您在 PropertyGrid 中选择的每种语言生成一个新的 .resx 文件。因此,您实际上不需要从资源中选择 值:当 CurrentCulture 更改(Thread.CurrentThread.CurrentCultureThread.CurrentThread.CurrentUICulture 更改)时,这会自动完成。先看看这些功能。
  • 您可以选择Change language at runtime in C# winformHow to make multi-language app in Winforms?。我个人建议做的事情非常清楚。
  • Change language at runtime in C# winform 它在运行时工作。非常感谢!
  • 这是一个选择。请注意,此处显示的方法不完整,不包括组件(和准组件)。外部调试器-可视化器可能发疯(或其他您目前可能不感兴趣的东西)

标签: c# .net winforms resources custom-controls


【解决方案1】:

鉴于问题的描述和应用于自定义控件的 ResourceKey 属性的 Description 属性,您似乎正在本地化您的应用程序,因此设置 -将父窗体的 Localizable 属性改为true

这会更改表单初始化中的一些细节。
如果您查看 Form.Designer.cs 文件,您会注意到添加了一些新部分:
平时:
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(YourForm));

现在有了新伙伴。在每个控件的初始化部分,都添加了resources.ApplyResources(this.controlName, "controlName");

您的自定义标签应显示,例如:

resources.ApplyResources(this.resourceLabel1, "resourceLabel1");

Control 派生的许多标准属性都是可本地化的(用[Localizable(true)] 属性装饰)。 Text property is of course among these。这些属性的值现在存储在用于不同本地化的资源文件中。因此,这些属性不再在 Designer.cs 文件中设置,并且在其他属性之前初始化。

您的 ResourceKey 属性未定义为 Localizable,因此已添加到 Designer.cs 文件中并在可本地化属性之后进行初始化。

▶ 一个简单的解决方法是将ResourceKey 属性定义为Localizable,这样它将在非本地化属性之前与Text 属性一起初始化。

[Localizable(true), Browsable(true)]
[Category("Appearance"), Description("Sets the resource key for localization")]
public string ResourceKey {
    get { return resourceKey; }
    set {
        if (resourceKey != value) {
            resourceKey = value;
            Invalidate();
        }
    }
}

请注意,这有点重大更改,您应该:

1 - 将 Localizable 属性添加到 ResourceKey 属性
2 - 从表单设计器中删除 ResourceLabel 控件
3 - 编译解决方案
4 - 将自定义 ResourceLabel 添加回原来的位置
5 - 在属性面板中设置所需控件的属性
6 - 运行应用程序或编译项目

查看你的Form的Designer.cs文件,看到ResourceKey属性消失了,它的值现在是通过resources.ApplyResource()设置的。

▶ 如果您不想使该属性可本地化,则必须在控件的初始化完成时稍后读取其值;例如,覆盖OnHandleCreated。请注意,在少数情况下可以在运行时重新创建控件的句柄(设置需要控件重新创建句柄的关键属性)。

注意
您不应该依赖属性的初始化顺序,并不能真正保证一个属性在另一个属性之前被初始化。在设计控件的行为时要考虑到这一点。

【讨论】:

  • 我理解对了吗?我的代码不能保证每次都以相同的方式执行。我在我的属性中添加了 Localizable 属性,它运行良好。
  • 如果您的代码在初始化阶段依赖于属性值,那么不:在这种情况下,作为一个很好的例子,属性值并不意味着以特定的顺序初始化(不是全部反正)。您可以在 Constructor 类中分配默认值,设置 [DefaultValue()] 属性并将此值与当前值等进行比较。通常,您最好不要假设属性已经初始化或在给定时间具有特定值(特别是当类第一次初始化时)。如果你解释一下这个属性的用途,你可能会有更好的建议。
  • 我使用此属性从资源文件中获取值并将值设置为 Text 属性。 var textFromResource = Resources.ResourceManager.GetString(ResourceKey, locale);
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-07
  • 1970-01-01
相关资源
最近更新 更多