locked
Properties that change other properties not rendering attribute(s) in designer RRS feed

  • Question

  • User632635755 posted

    Everything I've tried to search relating to my problem resulted in results that do not apply.

    I wrote a test web control that has two properties, ValueA and ValueB (both of type String).  Both properties store their values in viewstate as ViewState["ValueA"] and ViewState["ValueB"].  When ValueA changes, ValueB should be updated to ValueA as well.  When ValueB changes, ValueA should be updated to ValueB.  This is just a test for another control that is actually a one-way change, but for the test, I would like both to function this way.

    When I change, in the designer, ValueB, ValueA is set correctly, but looking at the source view of the page, ValueA is NOT being rendered as an attribute.  If I change ValueA in the designer, ValueA is being set correctly, but ValueB's attribute is not being updated.

    We have found a solution, but one that I don't necessary like so much.  What we have done in the property setter's is to get a reference to the ControlDesigner for the control.  Get a property descriptor for the OTHER property that we want to be updated, then call the designer's OnComponentChanged method passing in the old value, new value, and property descriptor.  This works, but is this really the only way to force the designer to update the other property's design-time attribute?

    This is for the Value2 property:

    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    [RefreshProperties(RefreshProperties.All)]
    public string Value2
    {
        get { return (string) ViewState["Value2"]; }
        set {
            string oldValue = (string) ViewState["Value1"];
            string newValue = value;
            
            ViewState["Value2"] = newValue;
            ViewState["Value1"] = newValue;
            
            IDesignerHost host = (IDesignerHost) this.Site.Container;
            ControlDesigner designer = (ControlDesigner) host.GetDesigner(this);
            PropertyDescriptor prop = TypeDescriptor.GetProperties(this)["Value1"];
            designer.OnComponentChanged(this, new ComponentChangedEventArgs(
                this, prop, oldValue, newValue
            ));
        }
    }



    Wednesday, October 31, 2012 2:47 PM

All replies

  • User3866881 posted

    This works, but is this really the only way to force the designer to update the other property's design-time attribute?

    Hi,

    If you only wanna to change each other's value, you can try to do this:

    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] 
    [RefreshProperties(RefreshProperties.All)] 
    public string Value2 
    { 
        get { return (string) ViewState["Value2"]; } 
        set { 
             
            ViewState["Value1"] = newValue; 
            } 
    }
    
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] 
    [RefreshProperties(RefreshProperties.All)] 
    public string Value1
    { 
        get { return (string) ViewState["Value1"]; } 
        set { 
            ViewState["Value2"] = newValue; 
            } 
    }
    
    //This will sychronize your Viewstates together.
    Thursday, November 1, 2012 9:25 PM
  • User632635755 posted

    I think I didn't relay the problem precise enough.  At runtime, everything works fine.  At design time, everything works fine with one exception.  When I change Value2 in the property grid, the Value1 property value gets changed/updated correctly but when I view the Source tab of the designer, Value1's updated value does not get written to the source.  Thus, if I close and re-open the aspx page, Value1's value is restored to what it was before I changed Value2.

    Below is the code I have (that works completely) ... if you take out the code in the A2 setter from where it gets a reference to the IDesignerHost and everything following that line (to the end of the setter), you can see the problem by adding the control to a page, selecting the control, view properties, change A2 to any value, then click Source at the bottom of the design window.  Inside the source view, you'll see that the value of A1 does not update at all.  If you keep the code in there that I currently have, the A1 value is updated properly and written as an attribute to the source.  What I have works, but I don't like accessing the designer from the control itself.

    public class CustomTextBox : WebControl
    {
        public CustomTextBox()
        {
            
        }
        
        [RefreshProperties(RefreshProperties.All)]
        public string A1
        {
            get {
                return (string) ViewState["A1"];
            }
            set {
                ViewState["A1"] = value;
            }
        }
        
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        [RefreshProperties(RefreshProperties.All)]
        public string A2
        {
            get { return (string) ViewState["A2"]; }
            set {
                string oldValue = (string) ViewState["A1"];
                string newValue = value;
                
                ViewState["A2"] = newValue;
                ViewState["A1"] = newValue;
                
                IDesignerHost host = (IDesignerHost) this.Site.Container;
                ControlDesigner designer = (ControlDesigner) host.GetDesigner(this);
                PropertyDescriptor prop = TypeDescriptor.GetProperties(this)["A1"];
                designer.OnComponentChanged(this, new ComponentChangedEventArgs(
                    this, prop, oldValue, newValue
                ));
            }
        }
    
        protected override void Render(HtmlTextWriter writer)
        {
            writer.Write(
                "A1: {0}, A2: {1}",
                this.A1 == null ? "(null)" : this.A1,
                this.A2 == null ? "(null)" : this.A2
            );
        }
    }


    Also, I changed the names of the values from Value1 and Value2 to A1 and A2 so they show at the top of the property sheet instead of the bottom.  Also, the property A2 is marked hidden so it does not written as an attribute/content to the control's source...this is on purpose and not part of my original explanation in my OP.

    Friday, November 2, 2012 12:21 PM
  • User3866881 posted

     [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]

    Hi,

    If you use this, this means you don't keep the value to A2, So that's the problem why you cannot save the A2's value immediately after it's upgrated.

    if you don't wanna it shown to the public in the editor, just use this attribute:

     [Browsable(false)]

    Friday, November 2, 2012 8:46 PM
  • User632635755 posted

    Ok, I think I still haven't relayed the issue properly.  You are correct in that A2 doesn't get saved.  That is by design.  We want A1 to be saved when we change the value of A2.  A2 is a Value property while A1 is the formatted text of A2, and it is also the property that is changed by the user.  A1 will be set by the user (Text property of the real control) while A2 will be the parsed version.  In the designer, we want both properties to be able to be changed by the user...but when one changes, the other should update it's value.  That works fine, but when A2 gets changed, A1 DOES get changed, but not saved to the design source (not serialized?).  The fix I posted in my OP works, but I just don't like it...but I guess I may have to live with it.

    Tuesday, November 6, 2012 11:13 AM
  • User3866881 posted

    when A2 gets changed, A1 DOES get changed, but not saved to the design source (not serialized?). 

    Yes, that's just want I mean. Because you've used Hidden, which won't serialized. 

    So please try my above way;)

    Tuesday, November 6, 2012 7:26 PM
  • User632635755 posted

    Ok, will try this again:

    Property A2 is marked as hidden.  Property A1 is *NOT* marked hidden.  (This really does not matter since the problem is the same when A2 is NOT hidden either).  When I change property A2, A1 is updated correctly but not saved to the source view html.  We do not want A2 to be saved to the design source, it's basically a property that allows A1 to be updated a different way using a different format, for this example I might add.  There's a little more too it in the resulting web control we are designing, but I've set up a test using the bare minimum just for trying to figure out this problem.

    Remember, it's when A2 gets changed and it updates the value for A1.  A1 is NOT writing to the design source html.  When I remove the attribute that marks A2 as hidden, A2 DOES get written to the design source, but the A1 property value that is updated and shown in the property grid does NOT write to the source, and that is the problem.  Man, this is difficult to describe.  Want me to post the HTML and web control sample that I've written to help show it?  It's written in Visual Studio 2008, not sure if the problem would exist in a more current version of VS.

    Wednesday, November 7, 2012 4:31 PM
  • User3866881 posted

    Hello again,

    As far as I see, I think you have to remove all the attributes or just do what I say to you.

    Maybe you can submit to http://connect.microsoft.com for more help to increase new features of the product;)

    Wednesday, November 7, 2012 7:57 PM