I have a simple interface like this:
interface IToolbarMaster {
ToolBar Toolbar { get; }
}
I added this Interface to my MasterPage and moved the field declaration of the Toolbar-Control to the Code Behind File:
public partial class Layout : ctrls.MasterPage, IToolbarMaster {
public global::Some.Web.Controls.ToolBar Toolbar;
(...)
}
My pages need to access this Toolbar Control via the Interface (we have a .FindMaster<IToolbarMaster>() Method) - but the code says, Layout doesn't implement IToolbarMaster
I could implement a property like
public ToolBar ToolBar { get { return this.Toolbar; } } // Different name spelling
But this looks really odd in my opinion.
I ran into a similar issue in VB using an auto property with a default value.
Public Property MessagePlaceHolder() As PlaceHolder = Me.phMessage
Apparently that doesn't work. I had to create the property the traditional way.
Public ReadOnly Property MessagePlaceHolder() As PlaceHolder
Get
Return Me.phMessage
End Get
End Property
Wow, I already got the answer, I was very close.
I tried this
public global::Some.Web.Controls.ToolBar Toolbar { get; }
but it didn't work. But as I added the setter everything was fine:
public global::Some.Web.Controls.ToolBar Toolbar { get; set; }
I'm leaving this for future reference, if anyone has this problem too.
Related
I am trying to implement a Custom Composite WebControl with "nested" properties, i.e., encapsulate a group of properties into a class.
For example, in this composite control, I have placed a button. I would like to be able to encapsulate relevant properties for the button into a class (e.g., buttonText, buttonStyle, etc.). This would make defining properties in multi-button/controls composite-control easier and consistent and intuitive.
Note: I would like for the encapsulated properties to appear grouped in the Properties dialog in VisualStudio, in a manner very similar to Style/Font.
Sample:
public class fooButtonProperties
{
[Category("Appearance"), Description("URL for the Profile page")]
public string URL { get; set; }
[Category("Appearance"), Description("Text to display"), DefaultValue("Profile")]
public string ButtonText { get; set; }
/// <summary>
/// Position of the control on the page, default is Right-Aligned
/// </summary>
[Category("Appearance"), Description("Position in the Header"), DefaultValue(PIONEERFramework.Web.UI.WebControls.PageHeaderFooter.Classes.DesignEnum.DesignLayoutEnums.HorizontalPositions.Right)]
///Here is the composite control
public PIONEERFramework.Web.UI.WebControls.PageHeaderFooter.Classes.DesignEnum.DesignLayoutEnums.HorizontalPositions PositionInHeader { get; set; }
}
public class myCustomClass: System.Web.UI.WebControls.CompositeControl
{
protected System.Web.UI.HtmlControls.HtmlLink myButton;
[Category("Appearance")]
public fooButtonProperties myButtonProperties { get { return _profileButtonProp; } }
private fooButtonProperties _myeButtonProp;
#region Constructor
public myCustomClass()
{
this._myeButtonProp = new fooButtonProperties ();
}
#endregion
}
Unfortunately, this approach dos not work. The new property myButtonProperties does not appear at all in the "Properies" dialog.
To create a nested property use the System.ComponentModel.DesignerSerializationVisibility attribute in your control like this:
[Category("Appearance")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public fooButtonProperties myButtonProperties { get { return _profileButtonProp; } }
The final property name will be "myButtonProperties-URL" (with a hyphen). You can also add this attribute to properties in your fooButtonProperties class for even more nesting.
Please note that you may have to close the aspx file and rebuild the solution to refresh the Properties window.
The Category attribute works in your control and in your nested class.
The Description attribute for the descriptions seems correct BUT it does not work which could be a bug in Visual Studio. I found this link:
https://www.beta.microsoft.com/VisualStudio/feedback/details/653335/webcontrol-property-descriptions-do-not-appear-in-property-window
Also I observed that no properties show descriptions.
Regards
Oli
I have a user control that contains a number of panel controls. The user control has logic to set the visibility of each panel, based on the values of some variables contained in the user control.
I would like to enhance this functionality by adding the following enumeration:
public enum Visibility
{
Default,
Always,
Never
}
where Default would use the current logic to set the panel's visibility, but Always would (obviously) make the panel always visible, and Never would always hide the panel.
I would also like to add a "nested" design-time property named something like PanelVisiblity that the developer could expand, and see the panel names listed below, and allow them to assign a value from the Visibility enumeration for each.
If I add properties like this:
public partial class MyControl : UserControl
{
public Visibility ActivePanel { get; set; }
public Visibility CodePanel { get; set; }
}
the ActivePanel and CodePanel properties appear in the Properties window in Visual Studio, and I can set them to one of the three values in the enum. However, when I refactored my code to try to create a nested property like this:
public partial class MyControl : UserControl
{
public class PanelVisibility
{
public enum Visibility
{
Default,
Always,
Never
}
public Visibility ActivePanel { get; set; }
public Visibility CodePanel { get; set; }
}
}
I do not get an expandable PanelVisiblity property, I get a disabled Visiblity property, where the value is the namespace of class, plus 'PanelVisibility'.
I have Googled a number of variations in phrasing this search, but have not been able to find anything like what I'm looking for.
Any direction would be greatly appreciated.
It seems that you are looking for the same functionality as a DockPanel offers.
I'd suggest you that instead of re-inventing the wheel you should use one the available implementations to you such as :
http://msdn.microsoft.com/en-us/library/system.windows.controls.dockpanel.aspx
http://dockpanel2012.codeplex.com/
https://github.com/dockpanelsuite/dockpanelsuite
Is there anyway to get the hostcontrol / parentcontrol from a region in PRISM C# WPF. Im trying to write an custom region behaviour that modifies the hostcontrol if there is no views in the region.
There is a HostControl property in RegionBehavior class but it is alwasy null. How do i set it ? or how to get the hostcontrol.
Thanks for advice!
[Export(typeof(CollapseRegionBehavior))]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class CollapseRegionBehavior : RegionBehavior, IHostAwareRegionBehavior
{
public DependencyObject HostControl { get; set; }
protected override void OnAttach()
{
if (this.Region.ActiveViews.Count() == 0)
{
}
}
}
Are you adding the RegionBehavior manually or do you register it in the bootstrapper in ConfigureDefaultRegionBehaviors?
It seems that if you add a behavior manually like this:
IRegion region = regionManager.Regions["MyRegion"];
region.Behaviors.Add("MyBehaviorKey", new MyBehavior());
the IHostAwareRegionBehavior interface has no effect. If you look at the PRISM source code in RegionBehaviorCollection.cs (Prism.Dektop.Regions) you'll clearly see that the Add method does not do anything related to the IHostAwareRegionBehavior interface.
However in RegionAdapterBase.cs, the interface is checked for in AttachDefaultBehaviors.
I ended up registering my RegionBehavior in the bootstrapper and checking the region name to see if there is work to be performed. Not very clean, but it works.
I need to add an attribute to some property in runtime (for design-time purposes). I know I can do this for classes:
TypeDescriptor.AddAttributes(typeof(MyType), new MyRuntimeAttribute());
But I can't find any way to do the same for properties.
Any suggestions?
UPD: The exactly task is following:
public class BaseClass {
public BaseClass(string name) { Name = name; }
public Name { get; set; }
}
public class Descendant1: BaseClass {
public Descendant1() : base("Default Name 1") { }
}
...
public class DescendantN: BaseClass {
public DescendantN() : base("Default Name N") { }
}
I want each of the descendants to have each own DefaultValueAttribute at the Name property with the corresponding default name. And I don't want to hardcode DefaultValueAttribute on each descentand :)
You can't dynamically add or remove attributes. Note that TypeDescriptor doesn't actually add an attribute to the class either: If you check the array that typeof(MyType).GetCustomAttributes(false) returns after you attach your attribute with MyRuntimeAttribute you'll notice that it isn't part of it.
Since you mention design-time, what you can do is dynamically modify attributes. Is that what you actually want to do?
See also:
Can attributes be added dynamically in C#?
Remove C# attribute of a property dynamically
You can also provide a control designer and in that designer you can override PreFilterProperties. While typically this is used to hide properties, it can also be used to add them.
http://www.codeproject.com/KB/webforms/HidingProperties.aspx
Is there a simple way to implement databinding when neither of both classes is of type Control?
In my case, I would like to bind a variable to a property of a custom ToolStripButton.
EDIT for clarification: when binding to a Control, I can use Control's DataBindings collection. However, I am searching for a way to bind properties regardless of the source and target Type.
EDIT: using winforms
You can probably do this by using Truss.
Truss provides WPF-style databinding for any class that implements INotifyPropertyChanged. It gives you a bit more flexibility in this, since it doesn't restrict the classes to being derived from a specific base class.
I use this Implemetation of IBindableComponent on the ToolStripButton, found here. The BindableToolStripButton allows you to use Databinding like with a normal Control.
[ToolStripItemDesignerAvailability(ToolStripItemDesignerAvailability.ToolStrip | ToolStripItemDesignerAvailability.StatusStrip)]
public class BindableToolStripButton : ToolStripButton, IBindableComponent
{
public BindableToolStripButton()
: base() { }
public BindableToolStripButton(String text)
: base(text) { }
public BindableToolStripButton(System.Drawing.Image image)
: base(image) { }
public BindableToolStripButton(String text, System.Drawing.Image image)
: base(text, image) { }
public BindableToolStripButton(String text, System.Drawing.Image image, EventHandler onClick)
: base(text, image, onClick) { }
public BindableToolStripButton(String text, System.Drawing.Image image, EventHandler onClick, String name)
: base(text, image, onClick, name) { }
#region IBindableComponent Members
private BindingContext bindingContext;
private ControlBindingsCollection dataBindings;
[Browsable(false)]
public BindingContext BindingContext
{
get
{
if (bindingContext == null)
{
bindingContext = new BindingContext();
}
return bindingContext;
}
set
{
bindingContext = value;
}
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public ControlBindingsCollection DataBindings
{
get
{
if (dataBindings == null)
{
dataBindings = new ControlBindingsCollection(this);
}
return dataBindings;
}
}
#endregion
}
Assuming you have a class MyClass implementing INotifyPropertyChanged, use it just like you would when binding to a control property:
bindableToolStripButton1.DataBindings.Add("Enabled", myClass1, "MyBooleanProperty");
Use dependency properties (your property in your ToolStripButton should be) and create a property for your variable in your other class and create a binding and set it to the property of your ToolstripButton.
I guess that's about the easiest way to do it.
EDIT: That's only for WPF...
Else implement INotifyPropertyChanged and when your variable changes, it should automatically change in your ToolStripButton.
For similar behaviour like Controls being bound to object properties, for any Type you can implement the same interfaces.
Based on that thought, you can subclass ToolStripButton (or desired Type to have bindings) and implement IBindableComponent for it. This works for all kinds of source and target Types as long as they're not sealed. For example, your tool strip button:
public class BindableToolStripButton : ToolStripButton, IBindableComponent {
//...
This will cause the BindableToolStripButton to have its own .DataBindings property whereas the base ToolStripButton class doesn't have such a propery.
You would need to follow through on filling out implementation details using examples seen here from Microsoft for ISite, IBindableComponent, IComponent and any inherited interfaces.
Then you would add Binding instances to any instance of BindableToolStripButton.
(Note: I only have fragements so will make my first community wiki post - and we'll see how that goes... )
I written some basic databinding stuff through reflection. It works on any object and doesn't need to implement something special (no INotifyPropertyChanged, it just works) it is part of my editor at http://github.com/filipkunc/opengl-editor-cocoa look at HotChocolate/Bindings (like re-implementation of Cocoa KVC, KVO into .NET) folder. You can see it in action in HotChocolateTest project.
There is another quick and simple solution which consists in creating properties in the Form, and bind them:
public MyForm : Form
{
...
public bool CanDelete
{
get { return deleteToolStripButton.Enabled; }
set { deleteToolStripButton.Enabled = value; }
}
public MyForm()
{
...
this.DataBindings.Add("CanDelete", this.MyModel, "DeleteAllowed",
false, DataSourceUpdateMode.Never);
...
}
}
Assuming that MyModel contains a DeleteAllowed property which notifies its changes.