Follow up to this question:
Winforms Style / UI Look and Feel Tips
So I have created my "base controls" from which other controls inherit from. For testing, I am trying to change one of the base label's font. But it is not propagating to the controls that inherit from it. On one of the forms, I can see the designer file is setting the properties for the control, so my base control's properties are getting overridden.
On the base control's I am using the Constructor to set the default properties. Should I be using a different event? If so, which one.
Here is the code for one of the base controls based on comment request...
Public Class InfoLabel
Inherits Label
Public Sub New()
' This call is required by the Windows Form Designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
Me.Font = New System.Drawing.Font("Tahoma", 14.25!)
Me.ForeColor = System.Drawing.Color.FromArgb(CType(CType(49, Byte), Integer), CType(CType(97, Byte), Integer), CType(CType(156, Byte), Integer))
Me.AutoSize = False
End Sub
End Class
The base controls show on the projects toolbox on the winform editor. Controls are then drag/drop from the toolbox.
Your problem is your custom control's InitializeComponent() method. I have no idea why that is there. You would get that method automatically if you were implementing a UserControl, but inheriting from a standard control that method should not be there. With your base class having an InitializeComponent() method and your subclass also having one, someone is overwriting someone else.
I just subclassed a label in C#. I dragged this on my form and the font displayed as the new font, not the base (Label) class's font.
using System.Drawing;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public class MyLabel : Label
{
public MyLabel()
{
Font = new Font("Candara", 14);
}
}
}
I then created a second label, called MySubLabel which inherited from the MyLabel class. When I changed the ForeColor on the MyLabel class, the MySubLabel automatically updated.
So this should work.
Caveat: in Visual Studio you need to recompile the assembly before trying to see updates in the designer.
Related
I have a winform custom control that looks like :
Public Class MyCustomControl
Inherits Control
Implements INotifyPropertyChanged
'Some textboxes...
private Textbox1 as textbox
private Textbox2 as textbox
private Textbox3 as textbox
'Control value
Property Value as MyCustomClass
get
'Extract some values from textboxes and return MyCustomClass (a separate custom object)
end get
Set(value As MyCustomClass)
'Set the values of the textboxes from the Value object
end Set
end Property
end class
I would like to insert this object in a winform and I would like my control to be "compatible" with errorProvider. Such that if I insert an errorProvider in the form and I call : errorProvider.SetError(MyCustomControl, "Error message"), it will show the error message on a specific text box in my custom control according to a custom logic.
Does anyone know which interface should be implemented or how to that please ?
Thanks. Cheers,
What you're trying to do would be better achieved with a UserControl, instead of inheriting directly from Control. (Having three TextBox instances inside your control is a good indication here.) In your UserControl you have a couple of options:
Add an ErrorProvider component and hook it up to each TextBox; or
For each TextBox expose it by making it public or via a public property, and then in your form hook it up to the form's ErrorProvider.
Ideally, you would use a BindingSource and data bind each TextBox, with the ErrorProvider.DataSource being set to your BindingSource.
I have all the styling, triggers, etc. down for ListView and ListViewItem, and I want to turn them into user controls. How do I make sure that these two "match up" with each other, so that MyListView accepts MyListViewItems as content? Also, considering that I must end the ListView tag by the end of the user control XAML file, I am not sure how I would add items to it.
If you want them to be reusable with different data sets, especially through binding, you should stay away from UserControls and just make custom controls derived from the original types. In that case you create a standalone MyListView.cs and MyListViewItem.cs and all of the XAML for the controls goes into default Styles (usually also containing a ControlTemplate) in Themes/Generic.xaml. You can see an example of this setup by just adding a WPF Custom Control to your WPF project from Add New Item.
Once you've created the .cs files for your custom controls you just need to override a few methods from the base ItemsControl to use MyListViewItem as the item container control. The ListView would end up like this:
public class MyListView : ListView
{
static MyListView()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(MyListView), new FrameworkPropertyMetadata(typeof(MyListView)));
}
protected override DependencyObject GetContainerForItemOverride()
{
return new MyListViewItem();
}
protected override bool IsItemItsOwnContainerOverride(object item)
{
return item is MyListViewItem;
}
}
You can now use your custom MyListView exactly as you would a normal ListView, including binding to ItemsSource.
Inheritance should take care of that for you. In other words, if you have two user controls, the first one with a basic element of ListView (not UserControl) and the other of ListViewItem (again, not UserControl), and you make sure they extend ListView and ListViewItem respectively in the .cs code, the following should work equally:
ListView lv = new ListView();
lv.Items.Add(new ListViewItem());
or
MyListView mlv = new MyListView();
mlv.Items.Add(new myListViewItem()); //If your myListView extends ListView, and myListViewItem extends ListViewItem in your user control files, of course
In case you are looking for a XAML solution, you should import your namespace at the top
xmlns:myControls="WhateverYourNamespaceAndAssemblyAre"
and on you page/window/whatever
<myControls:myListView>
<myControls:myListViewItem/>
<myControls:myListViewItem/>
</myControls:myListView>
In Visual Studio 2008, when I add some controls to form the designer creates some codes regarding the properties of the control automatically. Now, I'm using my own user controls and by adding them to the form, the designer again creates the code lines automatically, in this case the property FONT is one of those that I don't want the designer to add it since it overwrites the font setting in the upper level. Anyone knows how I can set which properties to be set in designer?
The designer only adds a line of code changing a property's value if it determines that the value is different from the DefaultValue[Attribute].
If your custom control wants to change what the default value of the Font property is (or any other base-class property), you have to perform a little wizardry:
public class MyControl : Control
{
public MyControl()
{
base.Font = new Font("Arial", 9.75f);
}
[DefaultValue(typeof(Font), "Arial, 9.75pt")]
public new Font Font
{
get { return base.Font; }
set { base.Font = value; }
}
}
Notice the 'new' keyword on the Font property? Font is not virtual, so you can't override it and we don't want to do that. You override to change behavior. We don't want to alter the behavior (which is why the code simply redirects back to the base), we just want to expose a new DefaultValue. This tricks the designer into considering the new default for your control.
We also make sure that our Font property has that value when it is constructed.
I would like to create a Silverlight custom control using C# only, without any xaml.
Here is my work so far (stripped down to the bare minimum for the question):
I tried to inherit User control as follows:
public class myControl: UserControl
{
// class code
}
And adding it to the LayoutRoot:
myControl control = new myControl();
LayoutRoot.Children.Add(control);
The control is added, but its invisible!!
How can i make it visible ? Is there something i missed ?
edit: The only visual element in my contorl is a grid with an image background
Your Usercontrol will be empty and have no visual effect until you give it a child control via it's Content property.
Well unless you put a template in place or add elements in code, UserControl is empty.
Maybe you could try inheriting from an existing control which has a template, like Button, etc and change that in code?
The current version of the Microsoft Live Labs PivotViewer control for SilverLight 4 has no way to style the elements of the control. Looking at the control in Reflector, I can see much of the style info is set in a ResourceDictionary in the assembly (assets/defaultcolors.xaml). What I would like to do is create my own copy of this file, then replace it at runtime on the PivotViewer control.
By subclassing the PivotViewer control and overriding OnApplyTemplate I can grab the child elements and set properties such as Background. I have not had any success Clear()'ng the MergedDictionaries and adding in my own:
public override void OnApplyTemplate() {
base.OnApplyTemplate();
/* can change things this way */
CollectionViewerView cvv = ((CollectionViewerView)((Grid)this.GetTemplateChild("PART_Container")).Children[0]);
((Grid)cvv.Content).Background = new SolidColorBrush(Colors.Black);
/* can't change things this way */
CustomDictionary gd = new CustomDictionary();
cvv.Resources.MergedDictionaries.Clear();
cvv.Resources.MergedDictionaries.Add(gd);
}
I'm afraid this isn't going to work in Silverlight because it uses only Static Resources. ( Styles Don't Update )
Changing a resource dictionary only works before InitializeComponent() is called, which is called in the constructor of the PivotViewer.
I've been trying to style the PivotViewer Control too. I hope there is another way, besides searching through the Visual Tree and changing properties.