How to set defaults for control properties?

Answered
0
0

Dear Team,

 

I have a quite basic question about how to set the default attribute values for all of my controls across the whole application.

For example all my DGVs should disallow resizing of rows, disallow multiselect, etc.

My naive approach is to derive the a custom control (e.g. DataGridViewExt) with pre-set attributes and use it across the application.

Programmatically this works quite well.

The problem is that in the VS designer properties view of the control instance the property values still appear in bold to indicate that the set value differs from the property decoration (e.g. [DefaultValue(false)] public property AllowUserToResizeRows …)

Is there a right way to re-decorate the properties, so they do not appear bold in VS designer properties list?

This would be really helpful, as this will show me what attributes are changed in the current instance only.

 

I will try a somewhat cumbersome approach to shadow the properties, as suggested in this SO thread

https://stackoverflow.com/questions/163611/changing-the-defaultvalue-of-a-property-on-an-inherited-net-control

 

Thanks,

Kizaemon

  • You must to post comments
Great Answer
0
0

Hi,

Thanks for your post. I tried as below and it looks all right.

Snippet

using System.ComponentModel;
 
namespace UIExtensions
{
    public class DataGridViewExt : Wisej.Web.DataGridView
    {
        public DataGridViewExt()
        {
            base.ShowColumnVisibilityMenu = false;
            base.AllowUserToResizeRows = false;
            base.AutoGenerateColumns = false;
        }
 
        [DefaultValue(false)]
        public new bool ShowColumnVisibilityMenu
        {
            set
            {
                base.ShowColumnVisibilityMenu = value;
                Invalidate();
            }
            get { return base.ShowColumnVisibilityMenu; }
        }
 
        [DefaultValue(false)]
        public new bool AllowUserToResizeRows
        {
            set
            {
                base.AllowUserToResizeRows = value;
                Invalidate();
            }
            get { return base.AllowUserToResizeRows; }
        }
 
        [DefaultValue(false)]
        public new bool AutoGenerateColumns
        {
            set
            {
                base.AutoGenerateColumns = value;
                Invalidate();
            }
            get { return base.AutoGenerateColumns; }
        }
    }
}
  • Kizaemon
    Tiago, thank you for your confirmation. I hoped for a better solution than shadowing individual properties, but shadowing reasonably solves the issue. Anyways this is a problem in .NET framework, rather than issue with Wisej.
  • You must to post comments
0
0

A bit more in depth about properties and Visual Studio designer serialization:

  • The Visual Studio designer recognizes inherited values only at the container level. If you create a derived container (Form, Page, UserControl), the property values set in the base class, also for child controls, are recognized as the default value and override the DefaultValueAttribute. It’s not a .NET feature or issue, it’s the Visual Studio Designer that works like that (it can be changed easily though). All Wisej controls implement their own designer but still within the Visual Studio infrastructure.
  • When not overridden by the the designer and inherited values from a base container class, the designer relies on System.ComponentModel. Which uses either the DefaultValueAttribute or the ShouldSerialize{Name} and Reset{Name} pattern (which gives you a lot more flexibility:
private bool ShouldSerializeShowHeader()
{
    return this._showHeaderCount > 3; // just to make it weird.
}

private void ResetShowHeader()
{
    this._showHeaderCount = 0;
}

* The accessor can be private, protected or public. Makes no different to VS, it will still use these methods because the pattern is in System.ComponentModel. For property extenders, simply add the Control target argument.
  • We have added a property filter to the VS designer in another product we have (PPJ Framework used for Gupta migrations, which is now using Wisej for the web version) to implement what is (should have been) the more logical way where the initialization value of the property is the default value in absence of a local definition of DefaultValue or ShouldSerialize. However doing to in Wisej would break existing WinForms code that expects property values to be propagated when the control is used in a container. IMO it’s a lot better to be able to change the value of a base class and update all usage, but that’s not the way VS sees it. If you want to change the default value, as Tiago showed, you need to override or shadow the property and explicitly add DefaultValueAttribute or the ShouldSerialize{Name} method.
  • We could add an option to containers to use the base values in the InheritedPropertyDescriptor instance used by VS but I’m not sure it would be beneficial. It’s probably better to use more component-oriented code and encapsulate functionality in a class and expose only what matters. In fact, in Wisej 2.0 we have added the possibility to design any control class, not just UserControl – this way it’s easier to extend say a Button or a TextBox and use the designer.

EOM, HTH

 

  • You must to post comments
0
0

To share my findings.

Decorating with MetadataType attribute does not yield the expected behavior.

Shadowing properties seem to work well. I am not sure if call to Invalidate() is required.

I will go for shadowing the properties.

 

 

using System;
using Wisej.Web;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
 
namespace UI.Controls
{
    [MetadataType(typeof(DataGridViewExtMetaData))]
    public partial class DataGridViewExt
        : Wisej.Web.DataGridView
    {
        public DataGridViewExt()
        {
            this.AllowUserToResizeRows = false;
            this.AutoGenerateColumns = false;
        }
 
        // works
        [DefaultValue(false)]
        public new bool AutoGenerateColumns {
            set { base.AutoGenerateColumns = value; Invalidate(); }
            get { return base.AutoGenerateColumns; }
        }
    }
 
    public class DataGridViewExtMetaData
    {
        // does not work
        [DefaultValue(false)]
        public bool AllowUserToResizeRows { get; set; }
    }
}



  • You must to post comments
Showing 3 results
Your Answer

Please first to submit.