WinForms strings in resource files, wired up in designer

后端 未结 5 2047
星月不相逢
星月不相逢 2021-02-05 12:58

I\'m trying to localise a WinForms app for multiple languages. I\'m trying to find a way to set my form labels/buttons text properties to read from the resources file in the des

5条回答
  •  迷失自我
    2021-02-05 13:28

    Easy enough to implement, by the way, this can be done for any type of control you like to bind to a resource, or any other class. I do this for static classes like my application settings as well.

    Entering code like this:

    textBox2.DataBindings.Add("Text", source, ".");  
    

    is not giving me a "good feeling", never mind the spelling

    Here is a litle sample of the above label that provides a dropdown on the resources of a application.

    First the control, contains 1 new property named ResourceName the magic comes from the editor, this one is specified in the annotation above the property and is called ResourceDropDownListPropertyEditor

    [Editor(typeof(ResourceDropDownListPropertyEditor), typeof(System.Drawing.Design.UITypeEditor))]
    

    The code for the label class:

    /// 
    /// Label bound to resource
    /// 
    /// 
    /// The bitmap does not appear in the Toolbox for autogenerated controls and components.
    /// https://docs.microsoft.com/en-us/dotnet/framework/winforms/controls/how-to-provide-a-toolbox-bitmap-for-a-control
    /// 
    [ToolboxBitmap(typeof(Label))]
    public partial class ResourceLabel : Label
    {
    
        /// 
        /// backing field for the resource key property
        /// 
        private string mResourceName;
        [Browsable(true)]
        [DefaultValue("")]
        [SettingsBindable(true)]
        [Editor(typeof(ResourceDropDownListPropertyEditor), typeof(System.Drawing.Design.UITypeEditor))]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        [Description("Select the resource key that you would like to bind the text to.")]
        public string ResourceName
        {
            get { return mResourceName; }
            set
            {
                mResourceName = value;
                if (!string.IsNullOrEmpty(mResourceName))
                {   
                    base.Text = Properties.Resources.ResourceManager.GetString(mResourceName);
                }
            }
        }
    
        /// 
        /// Designer helper method: https://msdn.microsoft.com/en-us/library/ms973818.aspx
        /// 
        /// true if XXXX, false otherwise.
        private bool ShouldSerializeResourceName()
        {
            return !string.IsNullOrEmpty(ResourceName);
        }    
        /// 
        /// Will be default text if no resource is available
        /// 
        [Description("default text if no resource is assigned or key is available in the runtime language")]
        public override string Text
        {
            get { return base.Text; }
            set
            {
                // Set is done by resource name.
            }
        }
    }
    

    Here is the class used for the drop down:

    /// 
    /// used for editor definition on those properties that should be able 
    /// to select a resource
    /// 
    /// 
    class ResourceDropDownListPropertyEditor : UITypeEditor
    {
        IWindowsFormsEditorService _service;
    
        /// 
        /// Gets the editing style of the  method.
        /// 
        /// An ITypeDescriptorContext that can be used to gain additional context information.
        /// Returns the DropDown style, since this editor uses a drop down list.
        public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
        {
            // We're using a drop down style UITypeEditor.
            return UITypeEditorEditStyle.DropDown;
        }
    
        /// 
        /// Displays a list of available values for the specified component than sets the value.
        /// 
        /// An ITypeDescriptorContext that can be used to gain additional context information.
        /// A service provider object through which editing services may be obtained.
        /// An instance of the value being edited.
        /// The new value of the object. If the value of the object hasn't changed, this method should return the same object it was passed.
        public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
        {
            if (provider != null)
            {
                // This service is in charge of popping our ListBox.
                _service = ((IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService)));
    
                if (_service != null)
                {
    
    
                    var items = typeof(Properties.Resources).GetProperties()
                                .Where(p => p.PropertyType == typeof(string))
                                .Select(s => s.Name)
                                .OrderBy(o => o);
    
                    var list = new ListBox();
                    list.Click += ListBox_Click;
    
                    foreach (string item in items)
                    {
                        list.Items.Add(item);
                    }
                    if (value != null)
                    {
                        list.SelectedValue = value;
                    }
    
                    // Drop the list control.
                    _service.DropDownControl(list);
    
                    if (list.SelectedItem != null && list.SelectedIndices.Count == 1)
                    {
                        list.SelectedItem = list.SelectedItem.ToString();
                        value = list.SelectedItem.ToString();
                    }
    
                    list.Click -= ListBox_Click;
                }
            }
    
            return value;
        }
    
        private void ListBox_Click(object sender, System.EventArgs e)
        {
            if (_service != null)
                _service.CloseDropDown();
    
    
        }
    }
    

    In the end what you get will look like this at design-time:

    The resource names are created when you drop the control on your form, changes are not seen till you re-compile and close/open the form or drop a new label on the form.

提交回复
热议问题