views:

14

answers:

1

Adding smart tags in VS2010 (or VS2008 for that matter) to my control makes VS crash.

The following designer is used for the action list:

internal class DataEditorDesigner : ComponentDesigner {
[...]
    public override DesignerActionListCollection ActionLists {
        get {
            var lists = new DesignerActionListCollection();
            lists.AddRange(base.ActionLists);
            lists.Add(new DataEditorActionList(Component));
            return lists;
        }
    }
}

internal class DataEditorActionList : DesignerActionList {
    public DataEditorActionList(IComponent component) : base(component) {}
    public override DesignerActionItemCollection GetSortedActionItems() {
        var items = new DesignerActionItemCollection();
        items.Add(new DesignerActionPropertyItem("DataSource", "Data Source:", "Data"));
        items.Add(new DesignerActionMethodItem(this, "AddControl", "Add column..."));
        return items;
    }
    private void AddControl() {
        System.Windows.Forms.MessageBox.Show("dpa");
    }
}

The DataSource property is declared as such:

    [AttributeProvider(typeof (IListSource))]
    [DefaultValue(null)]
    public object DataSource {
[...]

Any ideas on how to debug it?

A: 

I've found the solution. It's necessary to add wrapper properties to DesignerActionList classes, that's where they're read from, not from the actual component. Also, it's necessary to write such code:

internal static PropertyDescriptor GetPropertyDescriptor(IComponent component, string propertyName) {
    return TypeDescriptor.GetProperties(component)[propertyName];
}

internal static IDesignerHost GetDesignerHost(IComponent component) {
    return (IDesignerHost) component.Site.GetService(typeof (IDesignerHost));
}

internal static IComponentChangeService GetChangeService(IComponent component) {
    return (IComponentChangeService) component.Site.GetService(typeof (IComponentChangeService));
}

internal static void SetValue(IComponent component, string propertyName, object value) {
    PropertyDescriptor propertyDescriptor = GetPropertyDescriptor(component, propertyName);
    IComponentChangeService svc = GetChangeService(component);
    IDesignerHost host = GetDesignerHost(component);
    DesignerTransaction txn = host.CreateTransaction();
    try {
        svc.OnComponentChanging(component, propertyDescriptor);
        propertyDescriptor.SetValue(component, value);
        svc.OnComponentChanged(component, propertyDescriptor, null, null);
        txn.Commit();
        txn = null;
    } finally {
        if (txn != null)
            txn.Cancel();
    }
}

and then use it:

[AttributeProvider(typeof (IListSource))]
public object DataSource {
    get { return Editor.DataSource; }
    set { DesignerUtil.SetValue(Component, "DataSource", value); }
}

and so on for other properties.

sthalik