I'm building a webpart for Sharepoint 2010. I can create custom properties which are editable through the Sharepoint user interface. No problem there.
The problem is: I want to use a custom object(Properties.cs) to define those same properties(and keeping the editing functionality available), rather than dumping all code in the Webpart.cs like it's shown on the internet.
Is there a way to do this? Because I don't want to pump all my properties(editable or not) in the webpart class.
Yes, you can do it... by using inheritance and creating base classes as follows
1- first create a base class inheriting from WebPart class with override CreateChildControls method e.g
<XmlRoot("MyWebPartBase")> _
<ToolboxItemAttribute(True)> _
Public Class BaseWebPart
Inherits WebPart
Protected Overrides Sub CreateChildControls()
Dim control As Object = Page.LoadControl(ascxPath)
If control IsNot Nothing Then
control.WebPartControl = Me
Controls.Add(CType(control, Control))
End If
End Sub
'Add public properties here
End Class
2- Implement you properties in this base class and Inherent your webparts from above mentioned base class rather then webpart class.
3- Create a base class for user controls implementing public properties to access them in user control e.g.
Public Class BaseUserControl
Inherits UserControl
Private _WebPartControl As BaseWebPart
Public Property WebPartControl As BaseWebPart
Get
Return _WebPartControl
End Get
Set(ByVal value As BaseWebPart)
_WebPartControl = value
End Set
End Property
Public ReadOnly Property WebPartID() As String
Get
Return WebPartControl.ID
End Get
End Property
End Class
Related
I'm using VB.Net in Visual Studio 2012 for a project with a web service I can't change at all. The problem is that VB does not generate all the properties it should generate.
I added the web service as a reference service. According to the XSD, collectionRAEEDataType class should include properties as receiver, referenceNumber, sigCode. But, when I try to access them, two of them are not shown: sigCode and responsabilitySystemData.
I've contacted the support email of the web service and they tell me that yes, that in the Java service the class is generated with those fields:
public class CollectionRAEEDataType {
protected String sigCode;
protected RegisteredInfoDataType responsabilitySystemData;
...
}
But in Reference.vb I get this:
Partial Public Class collectionRAEEDataType
Inherits Object
Implements System.ComponentModel.INotifyPropertyChanged
Private itemField As Object
Private receiverField As receiverType
Private referenceNumberField As String
Private assignmentOfficeIdField As String
'''<remarks/>
<System.Xml.Serialization.XmlElementAttribute("responsabilitySystemData", GetType(registeredInfoDataType), Form:=System.Xml.Schema.XmlSchemaForm.Unqualified, Order:=0), _
System.Xml.Serialization.XmlElementAttribute("sigCode", GetType(collectionRAEEDataTypeSigCode), Form:=System.Xml.Schema.XmlSchemaForm.Unqualified, Order:=0)> _
Public Property Item() As Object
Get
Return Me.itemField
End Get
Set
Me.itemField = value
Me.RaisePropertyChanged("Item")
End Set
End Property
'''<remarks/>
<System.Xml.Serialization.XmlAttributeAttribute()> _
Public Property receiver() As receiverType
Get
Return Me.receiverField
End Get
Set
Me.receiverField = value
Me.RaisePropertyChanged("receiver")
End Set
End Property
...
As you can see, the property receiver is ok, but responsabilitySystemData and sigCode are not properties.
Do you know how could I solve this problem?
Thanks a lot.
I answer myself. I had to instantiate the Item field with the type I wanted, registeredInfoDataType or collectionRAEEDataTypeSigCode.
For example,
MyElement.Item = New registeredInfoDataType()
Thank you.
The Situation-
Have EF database entities with collections of other database entities as navigation properties all of which are not exposed outside of the project. Each of these entities are nested in base classes that allow public read and protected set access to the Db entity's property values and are the classes the business layer will work with. So these base classes also need collections of their Db entity's navigation properties.
What I have now-
I am still working on how I want the data layer to interact with with the other layers that reference it. So I have been experimenting with creating collection classes that can be set equal to a collection of Db entities and create a collection of the base class that the Db entity is nested in. The collection is then exposed outside the class though an interface as well as the base class. The interface gives access to some custom methods of collection class like accepting DTOs and prebuilt quires but would hide any Add methods.
The Problem-
I would like to create a generic base class for the collections but cant seem to find a way. I have gotten close to something workable but it was ugly and confusing. Below is an outline of what I'm working with. The narrowing operators in the entity class work well. I would rather have widening operators and narrowing operators in the base class so I could keep the New method private for the base classes but I don't want to expose the actual database entities outside the Data Layer.
Interops Namespace referenced by all projects in solution-
Public Interface IGenericEntity
End Interface
Public Interface INavigationPropertyEntity : Inherits IGenericEntity
End Interface
Public Interface IDbEntityToExposedEntityCollection(Of TEntity As IGenericEntity)
'Used to hide Add method
End Interface
Public Interface IPublicEntity
ReadOnly Property NavProps As IDbEntityToExposedEntityCollection(Of INavigationPropertyEntity)
End Interface
Data Layer project-
-Database Entities
Friend Class DbEntity1
Public Shared Narrowing Operator CType(ByVal value As DbEntity1) As NavigationPropertyEntity
Return New NavigationPropertyEntity(value)
End Operator
End Class
Friend Class DbEntity2
Public Sub New()
NavigationPropertyDbEntities = New HashSet(Of DbEntity1)
End Sub
Public Property NavigationPropertyDbEntities As ICollection(Of DbEntity1)
Public Shared Narrowing Operator CType(ByVal value As DbEntity2) As PublicEntity
Return New PublicEntity(value)
End Operator
End Class
-Exposed Base Classes
Public Class NavigationPropertyEntity : Implements INavigationPropertyEntity
Private _value As DbEntity1
Friend Sub New(value As DbEntity1)
_value = value
End Sub
End Class
Public Class PublicEntity : Implements IPublicEntity
Dim _value As DbEntity2
Friend _NavProps As DbEntityToPublicEntityCollection(Of INavigationPropertyEntity, DbEntity1, NavigationPropertyEntity)
Public ReadOnly Property NavProps As IDbEntityToExposedEntityCollection(Of INavigationPropertyEntity) Implements IPublicEntity.NavProps
Get
Return _NavProps
End Get
End Property
Friend Sub New(value As DbEntity2)
_value = value
_NavProps = new DbEntityToPublicEntityCollection(Of INavigationPropertyEntity, DbEntity1, NavigationPropertyEntity)(_value.NavigationPropertyDbEntities)
End Sub
End Class
-Entity Specific Collection
Friend Class DbEntityToPublicEntityCollection(Of IEnt As INavigationPropertyEntity, DbEnt As DbEntity1, ExpEnt As NavigationPropertyEntity)
Inherits HashSet(Of IEnt)
Implements IDbEntityToExposedEntityCollection(Of IEnt)
Public Sub New(value As HashSet(Of DbEnt))
For Each ent In value
Dim exp As NavigationPropertyEntity = ent
Dim i As INavigationPropertyEntity = exp
MyBase.Add(i)
Next
End Sub
End Class
Additional Info Edit
The main issue is being able to have a generic collection declared something like,
Friend Class DbEntityToPublicEntityCollection(Of IEnt, DbEnt as class, ExpEnt As class)
because in the New sub ExpEnt cannot be converted to DbEnt and a TryCast will just result in a runtime error.
Like I said, I tried setting up classes that are inherited by the exposed and entity classes so a new method with a parameter for the exposed class could be set up but with trying to have the interfaces in there it got unmanageable pretty quick. Then again I have not worked much with making my own generic types before so I'm not sure if this is even a proper strategy.
Suppose I have the following class:
Public Class lbMenu
Inherits Form
...
Public Sub AddItem(header As String)
Dim item As New lbMenuItem()
item.Owner = Me
item.Header = header
Controls.Add(item)
End Sub
...
End Class
and also the following class:
Public Class lbMenuItem
Inherits Control
Private _Owner As lbMenu
Public Property Owner As lbMenu
Get
Return _Owner
End Get
Set(value As lbMenu)
_Owner = value
End Set
End Property
Private _Header As String
Public Property Header As String
Get
Return _Header
End Get
Set(value As String)
_Header = value
End Set
End Property
...
End Class
As you can see, I access the Owner property of lbMenuItem from the class lbMenu.
What I want is that nobody else can access the Owner property, or maybe just to read the value of the property. I think there is no way to do that but maybe there is a solution to reach a similar situation.
Any suggestions?
Edit:
I already considered passing the owner as a parameter in the constructor, but I want that anyone can access the lbMenuItem class. Anyone can create a new instance of the class, read and write many properties, etc. The only thing I don't want is that someone can write the Owner property. Someone can create a new instance of the class without having to pass an ownerMenu parameter to the New method (he can't know what ownerMenu is for). For the same reason, lbMenuItem can't be a nested class of lbMenu.
I'm trying to get the same result as with ContextMenuStrip and ToolStripMenuItem. ToolStripMenuItem has an Owner property (which in this case has read/write access) and an OwnerItem which is read-only.
So, is there a way to make the Owner property read-only but writable from the lbMenu class?
You could just have the Owner property private or read-only if you want to allow reading its value and set it in the constructor.
Edit:
Someone can create a new instance of the class without having to pass
an ownerMenu parameter to the New method
Well, you can have two constructors, one that accepts a lbMenu parameter, and one without. So, your code would look something like this:
Public Class lbMenu
Public Sub AddItem(header As String)
Dim item As New lbMenuItem(Me)
item.Header = header
Controls.Add(item)
End Sub
End Class
Public Class lbMenuItem
' Use this instead if you don't want the property to be accessible at all.
'Private Property Owner As lbMenu
Public ReadOnly Property Owner As lbMenu
Public Property Header As String
' Allow creating an instance of the class without having to pass/set the owner.
Public Sub New()
End Sub
Public Sub New(ownerMenu As lbMenu)
Owner = ownerMenu
End Sub
End Class
One last recommendation:
Based on the names of your classes, you might consider having a parent/child relationship between them (i.e., the lbMenuItem class would be a nested class within lbMenu). This will give you the advantage of being able to access the private members of lbMenu from a lbMenuItem instance.
Hope that helps.
Addressing the new points in your edit:
ToolStripMenuItem has an Owner property ... and an OwnerItem which is read-only.
That's exactly what I proposed (i.e., to use a read-only property). Note that the OwnerItem property isn't exposed as writable to any other class.
So, is there a way to make the Owner property read-only but writable
from the lbMenu class?
No, that's not possible. A read-only property is read-only, period. You can't expose its setter to a specific class. You can, however, limit the accessibility to its setter by using the keywords Friend, Private, or Protected:
Friend Set --> will make the setter accessible (make the property writable) inside the current project and read-only outside the project.
Private Set --> will make the setter accessible from the child classes.
Protected Set --> will make the setter accessible from the derived classes.
Take a look at this question to get a better idea on how to limit the accessibility of a property setter. It's about C#, but the concept is the same.
I'm writing a program in VB.NET and try to save different profiles via the application settings (project settings -> settings tab).
I created a Profile class and a collection class of that. If I choose this collection as settings type, I can add multiple objects with type System.Object, but I need to add my Profile object.
How can I add a collection of my Profile objects with the settings editor? Whats wrong with my code?
Profile.vb
Imports System.Configuration
<SettingsSerializeAs(Configuration.SettingsSerializeAs.Xml)> _
Public Class Profile
Public Property Name As String
Public Property ViewerCommand As String
Public Property ViewerPath As String
Public Property StartService As Boolean
Public Property StopService As Boolean
End Class
<SettingsSerializeAs(Configuration.SettingsSerializeAs.Xml)> _
Public Class ProfileCollection
Inherits CollectionBase
Public Shadows Function Add(ByVal ProfileObject As Profile) As Profile
MyBase.List.Add(ProfileObject)
Return ProfileObject
End Function
Public Shadows Sub Remove(ByVal ProfileObject As Profile)
MyBase.List.Remove(ProfileObject)
End Sub
End Class
A screenshot of the current behavior
The type is VNC_Manager.ProfileCollection for the setting called "Profiles".
On the right side there should be Name, ViewerCommand, ...
If I use VNC_Manager.Profile for type, I also can't see Name, ViewerCommand... So there seems to be a problem with the Profile class(?)
I'm trying to create a control (Parent Class) that uses a custom grid (Child Class). The grid has a series of constructors and methods for populating itself based on property values in the [parent] control.
The only way I found to make these property values available to the grid is by making them Shared but that's causing me all kinds of issues.
REQUIREMENTS
Properties in the control (parent) must be accessible to the grid (child).
Properties in the control must be visible in the design-time properties explorer.
The grid class must only be instantiable by the parent class.
As a side note: please indicate if your answer will allow me to share properties/methods back and forth between child and parent. That would be nice, but just a bonus.
Thanks ;)
EDIT - A VERY simple example based on my situation:
Partial Public Class catContent
Inherits System.Web.UI.UserControl
Protected Sub Page_Load(sender, e) Handles Me.Load
Page.Controls.Add(New CategoryResultGrid(category))
End Sub
Private Shared _product As String = String.Empty
Shared Property Product() As String
Get
Return _product
End Get
Set(ByVal value As String)
_product = value.Trim()
End Set
End Property
Private Class CategoryResultGrid
Inherits GridView
Sub New(ByVal category As String)
'How do I access "Product" here without sharing it?
End Sub
End Class
End Class
Do NOT use shared, it will break your app as soon as you put more than one of you custom control in your app.
If you only want the Grid to exist in the context of the Parent control, then consider exposing it similar to how the ListView control exposes its Items collection.
If you want your Grid to access fields in the (parent) Control there are several ways to do that. You could pass an instance of the Parent to the Grid, you can let the Grid use the standard Control methods to get its parent reference, or you can implement the Grid as an inner class of the Parent.