DataFieldConverter.GetStandardValues() returns and empty collection

L

Luis Ramírez

Hello everybody

I have been working on this issue for two days and I still working on...... Basically what I want to do is the next

1. Create a custom web control (it works fine). *
2. Create a custom designer for my custom web control (it works fine)
3. Create a custom component editor (it works fine)
4. My component editor will launch a windows form that will have a combobox. This combobox will be fill with the datafields names that will be taken from de datasource already selected

** My custom web control has a datasource, datamember and datakeyfield properties

Here is a an example of my custom web control design-time behavior
1. I drop my custom web control from the toolbox
2. I drop a dataset and I add n tables and n fields to the tables
3. I assign values to the datasource, datamember and datakeyfield
4. I do right-click to my custom web control, I select "Load editor..." (that's my verb caption
5. A windows form is showed. This window will have a combobox with the fields names of the selected datasource

My problem is number 5. The fields are not showed, when I call DataFieldConverter.GetStandardValues() it return
and empty collection. Why

I have post my all code, my code also has comments about what is happening when I debug it.

If someone can help me I will appreciate a lot.

Thanks in advance

(sorry for my english

Luis Ramírez

//***************************** custom web control, designer, editor *********

using System;using System.ComponentModel;using System.Collections;using System.ComponentModel.Design
using System.Windows.Forms.Design;using System.Windows.Forms;using System.Web.UI.Design
using System.Web.UI;using System.Diagnostics

namespace TestNamespac

//Step 1
[Designer(typeof(TestNamespace.CustomWebControlDesigner), typeof(IDesigner))
public class CustomWebControl : System.Web.UI.WebControls.WebContro

private object _dataSource


Bindable(true)
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden

public virtual object DataSource

get

return _dataSource

set

if ((value == null) || (value is IListSource) || (value is IEnumerable))

_dataSource = value

else

throw new ArgumentException()




public virtual string DataKeyField

get

string s = (string)ViewState["DataKeyField"]
return (s == null) ? String.Empty : s

set

ViewState["DataKeyField"] = value



public virtual string DataMember

get

string s = (string)ViewState["DataMember"]
return (s == null) ? String.Empty : s

set

ViewState["DataMember"] = value




//Step
public class CustomWebControlDesigner : System.Web.UI.Design.ControlDesigner, IDataSourceProvide

public override System.ComponentModel.Design.DesignerVerbCollection Verb

get

DesignerVerbCollection dvc = new DesignerVerbCollection()
dvc.Add(new DesignerVerb("Load editor...", new EventHandler(LoadEditor)))
return dvc



private void LoadEditor(object sender, EventArgs e

CustomWebControlEditor editor = new CustomWebControlEditor();
//I call EditComponent, I supposed that internally this call will be translated into EditComponent(null, this.Component, null), thats why context is always nul
//Is there any way I can call EditComponent directly, I mean replace Line 1(below) with something like: editor.EditComponent(context, this.Component, owner)
editor.EditComponent(this.Component); //Line


public string DataKeyField

get { return ((CustomWebControl)Component).DataKeyField;
set { ((CustomWebControl)Component).DataKeyField = value;


public string DataMember

get { return ((CustomWebControl)Component).DataMember;
set { ((CustomWebControl)Component).DataMember = value;


public string DataSource

get

DataBinding binding = DataBindings["DataSource"]

if (binding != null)

return binding.Expression
}
return String.Empty;
}
set
{
if ((value == null) || (value.Length == 0))
{
DataBindings.Remove("DataSource");
}
else
{
DataBinding binding = DataBindings["DataSource"];

if (binding == null)
{
binding = new DataBinding("DataSource", typeof(object), value);
}
else
{
binding.Expression = value;
}
DataBindings.Add(binding);
}
OnBindingsCollectionChanged("DataSource");
}
}

protected override void PreFilterProperties(IDictionary properties)
{
base.PreFilterProperties(properties);

PropertyDescriptor prop;

prop = (PropertyDescriptor)properties["DataSource"];
Debug.Assert(prop != null);

// We can't create the designer DataSource property based on the run-time property because these
// types do not match. Therefore, we have to copy over all the attributes from the runtime
// and use them that way.
System.ComponentModel.AttributeCollection runtimeAttributes = prop.Attributes;
Attribute[] attrs = new Attribute[runtimeAttributes.Count + 1];

runtimeAttributes.CopyTo(attrs, 0);
attrs[runtimeAttributes.Count] = new TypeConverterAttribute(typeof(DataSourceConverter));
prop = TypeDescriptor.CreateProperty(this.GetType(), "DataSource", typeof(string),
attrs);
properties["DataSource"] = prop;

prop = (PropertyDescriptor)properties["DataMember"];
Debug.Assert(prop != null);
prop = TypeDescriptor.CreateProperty(this.GetType(), prop,
new Attribute[] {
new TypeConverterAttribute(typeof(DataMemberConverter))
});
properties["DataMember"] = prop;

prop = (PropertyDescriptor)properties["DataKeyField"];
Debug.Assert(prop != null);
prop = TypeDescriptor.CreateProperty(this.GetType(), prop,
new Attribute[] {
new TypeConverterAttribute(typeof(DataFieldConverter))
});
properties["DataKeyField"] = prop;
}

#region Implementation of IDataSourceProvider
object IDataSourceProvider.GetSelectedDataSource()
{
object selectedDataSource = null;

DataBinding binding = DataBindings["DataSource"];
if (binding != null)
{
selectedDataSource = DesignTimeData.GetSelectedDataSource(Component, binding.Expression);
}

return selectedDataSource;
}

IEnumerable IDataSourceProvider.GetResolvedSelectedDataSource()
{
IEnumerable selectedDataSource = null;

DataBinding binding = DataBindings["DataSource"];
if (binding != null)
{
selectedDataSource = DesignTimeData.GetSelectedDataSource(Component, binding.Expression, DataMember);
}

return selectedDataSource;
}
#endregion
}

//step 3
public class CustomWebControlEditor : WindowsFormsComponentEditor
{
public override bool EditComponent(ITypeDescriptorContext context, object component, System.Windows.Forms.IWin32Window owner)
{
CustomWebControl myCustomWebControl = (CustomWebControl)component;
IServiceProvider site = myCustomWebControl.Site;
IComponentChangeService changeService = null;
DesignerTransaction transaction = null;
bool changed = false;

try
{
if (site!=null)
{
IDesignerHost designerHost= (IDesignerHost)site.GetService(typeof(IDesignerHost));
transaction = designerHost.CreateTransaction("TestTransaction");
changeService = (IComponentChangeService)site.GetService(typeof(IComponentChangeService));
if (changeService!=null)
{
try
{
changeService.OnComponentChanging(myCustomWebControl, null);
}
catch (CheckoutException ex)
{
if (ex==CheckoutException.Canceled)
return false;
throw ex;
}
}
}
try
{
CustomWebControlEditorForm frmEditor = new CustomWebControlEditorForm(myCustomWebControl, context);
if (frmEditor.ShowDialog(owner) == DialogResult.OK)
changed = true;
}
finally
{
if (changed && (changeService != null))
changeService.OnComponentChanged(myCustomWebControl, null,null,null);
}
}
finally
{

if (transaction != null)
if (changed)
transaction.Commit();
else
transaction.Cancel();
}
return changed;
}
}
}

//****** editor ************ I just send de constructor.
public class CustomWebControlEditorForm : System.Windows.Forms.Form

//step 5
public CustomWebControlEditorForm(CustomWebControl myCustomWebControl, ITypeDescriptorContext context)
{
InitializeComponent();
//context is null, why? always context will be null?
PropertyDescriptor pd = TypeDescriptor.GetProperties(myCustomWebControl)["DataKeyField"];
//The microsoft documentation says that if I call DataFieldConverter.GetStandardValues() it will return the data fields for the selected datasource.
//Note: pd.Converter is of type DataFieldConverter.
TypeConverter.StandardValuesCollection svc = pd.Converter.GetStandardValues(context);
//I call GetStandardValues() without context just to see what happens.
ICollection coll = pd.Converter.GetStandardValues();

// When I call pd.Converter.GetStandardValuesSupported() an exception is raised. why? the microsoft documentation doesn't mention anything about it.
// I supposed it happens because context is null.
// if (pd.Converter.GetStandardValuesSupported())
// {
// svc = pd.Converter.GetStandardValues(context);
// coll = pd.Converter.GetStandardValues();
// }

//If I would have the fields, here a would fill a combobox with the fields names.
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,013
Latest member
KatriceSwa

Latest Threads

Top