I have made a custom trackbar control, mostly as an exercise. I know i could/should have just inherited what i needed instead of reinventing the wheel, but i have learned a lot during my endeavour.
Now, i have a lot of properties, and all of them shows up in the designer apart from a couple of image properties. This is what i have, modelled on the other working properties (those are ints and Colors and what not, and they all work as expected...), so maybe i should be doing Images in some other way. Bottom line, i don't know what i'm doing :)
EDIT : My custom control is in a Windows Forms solution (VC# 2008 Express), and to clarify, my problem is that some of my control's properties (the Image properties) isn't showing in the properties-tab during design-time.
EDIT 2 : After reading up on DependencyProperty and totally failed to understand that concept (I'm very noob at programmin teh codez or what you gurus call this black voodoo magic??). I have gotten used to letting the IDE fix all my troubles, and i was pleased to see the IDE happily showing my other properties, such as Color BarColor, int Value etc. etc. Why would Image LeftImage be any different, a lot of the standard controls have Image properties and maybe it's naïve of me to think that the IDE can figure all of my mistakes out, but surely the guys at Microsoft did not construct a new editor every time they had to set an image property in their controls. My bet is that they reused something, which i should be able to do as well.
I'm stuck :(
Here's my crappy CoD3Z anyway:
private Image _LeftImage;
/// <summary>
/// Sets the small image appearing to the left of the trackbar
/// </summary>
[Description("The small image appearing to the left of the trackbar"),
Category("Appearance"),
DefaultValue(typeof(Image),"null"),
Browsable(true), EditorBrowsable(EditorBrowsableState.Always)]
public Image LeftImage
{
private get { return _LeftImage; }
set
{
if (value.Height != 16 || value.Width != 16)
{
_LeftImage = new Bitmap(value,new Size(16,16));
}
else _LeftImage = value;
Invalidate();
}
}
By the way, what is the difference between DefaultValue and DefaultValueAttribute?
Thanks for any pointers and help!
/Mikael
I have found something here:
http://msdn.microsoft.com/en-us/library/system.drawing.design.imageeditor.aspx
Consider this solved.
For Show the Image in the Designer you need to overrides the OnPaint Method drawing it.
DefaultValue is the same that DefaultValueAttribute. All Attributes in .NET are clases that inherits from System.Attribute, and all those class are something like Name*Attribute* where Attribute is fixed. Then "DefaultValue" is like an Alias.
Your example doesn't show what exactly is your problem but if you create custom control and want to access its properties from designer you should use smth like that:
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value", typeof(object), typeof(CustomControl),
new FrameworkPropertyMetadata(null, ValueChanged));
hope this helps you
Related
I've been wondering when should I use a Property or a Dependency Property in a custom control for a while, so I thought it'd be a good idea to ask.
Let's say I have a simple (I mean, really simple) UserControl with just a Button and a TextBlock inside it. Let's call the TextBlock "myTextBlock".
Now, if I knew I'll need to bind the Text of that TextBlock to something else, I'd go with a Dependency Property, and that's not a problem.
But what if I just need to set the Text property of the TextBlock to a certain value via XAML and leave it be?
Does it matter if I use a Property instead of a DependencyProperty?
Is one option faster/better than the other one, and if so, why?
Here is a sample with the two options:
public String ButtonText
{
get { return (String)GetValue(ButtonTextProperty); }
set { SetValue(ButtonTextProperty, value); }
}
public static readonly DependencyProperty ButtonTextProperty =
DependencyProperty.Register("ButtonText", typeof(String), typeof(MyUserControl),
new PropertyMetadata(String.Empty, OnButtonTextPropertyChanged));
private static void OnButtonTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
(MyUserControl)d.myTextBlock.Text = (String)e.NewValue;
}
And with just the Property:
public String ButtonText
{
get { return myTextBlock.Text; }
set { myTextBlock.Text = value; }
}
I usually go with the simple Property, but I don't know if that's the better approach to use here. Of course it works fine, that's not a problem.
Thanks in advance!
Sergio
I always ask these basic questions
Do I need this to be bindable, animations, or styles and have default
settings that a simple property can't offer for this control?
Do I need to preserve the XAML (expression) with this new property when I am going to serialize/deserialize this
control?
If yes, then I would use DependencyProperty. If not then I'd just use simple properties to be used within this control. It's similar to the question on whether you want to use fields vs properties in an object. My tip is use it when you need the framework's capabilities in your property as they give you more options. You want to know if you need those options or not.
Another reason you want to use DependencyProperty is because you have a base/child control relationship and you want other developers to be able to consume. Instead of you creating interfaces to expose to your control, you provide instant static getter/setter to read/modify the value of your control. You are already creating your interfaces when you create DependencyProperty.
When in doubt, always create simple properties/fields against your control.
I don't agree with the comment that always go with DependencyProperty because it's not cheap compared to a simple property.
For example, you want to make changes to the property and it was a DependencyProperty then chances are, I would need to manually edit the name of the property which is a string and is error-prone. Now compare that to a simple property that gives me a compile time check and I can find the references easily and make some changes to it.
I've had experiences where DependencyProperty was an overkill and should have just used simple properties and the intent would be clear for other developers to read.
I am trying to detect changes in the Application.Resources Resource dictionary, so I can automatically change the Titlebar to the Accent Colour when it updates. All of the XAML controls and elements change automatically, and when setting a solid colour brush to the address of the DSDFS brush, its internal value changes.
This is the code I have tried to use to detect the change:
public static DependencyProperty accent = DependencyProperty.Register("DictChange", typeof(ResourceDictionary), typeof(Shell), new PropertyMetadata(Application.Current.Resources, new PropertyChangedCallback(accent_PropertyChanged)));
public ResourceDictionary DictChange
{
get { return (ResourceDictionary)GetValue(accent); }
set { SetValue(accent, value); }
}
private static void accent_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
_app.SetTitlebar();
}
I'm assuming its wrong though, or I'm not sure if that is the right thing to do to detect changes. There was a previous iteration where I used Application.Current.Resources["SystemControlBackgroundAccentBrush"] as SolidColorBrush and tried to detect its property, but that didn't work either.
What am I doing wrong? Please help :)
It might not be wrong, but it's probably not the best solution available.
In WinRT XAML, we have this new ThemeResource that updates the resources automatically. The tricky bit is to find a way to bind the ApplicationView.GetForCurrentView().TitleBar.BackgroundColor to SystemControlBackgroundAccentBrush.
In my answer to this question, I created a Behavior that attaches a custom TitleBar to the page. If you modify the Background property to something like this -
<local:FullScreenModeTitleBarBehavior Background="{ThemeResource SystemControlBackgroundAccentBrush}" />
Now run the app and you will see the background color gets updated when you change the accent color of the system, as shown in the picture below -
Basically in your case, you just need to create a similar (& simpler?) Behavior that acts like a bridge to link the BackgroundColor of the TitleBar to the SystemControlBackgroundAccentBrush, via ThemeResource binding.
Hope this helps!
I'm assuming its wrong though, or I'm not sure if that is the right thing to do to detect changes.
You cannot detect the key-value changes in the Resource Dictionary by registering a DependencyProperty because the ResourceDictionay is not an ObservableCollection Class.
There are no build-in support to detect the key-value changes in a Resource Dictionary.
As a workaround, you can consider create an internal observable collection to detect the changes.
I am working on a WinForms application using Visual Studio 2008 (C#). The user interface of the concerning form consists of several SplitContainers.
When I tested the application after setting the Windows font size to 125%, the form didn't look any more as it should. There obviously was a problem with scaling. Therefore I've searched for a solution and found one here. The two following lines did the job for me:
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
As explained in the other question (in one of the answers, respectively), they have to be included for every container in the designer file. It works and scaling performs correctly. But on the other hand, I have to manually edit the designer file and that's something one actually shouldn't do. The added lines get lost every time I use the layout designer.
EDIT: Just to clarify: These two properties are not shown in the designer gui.
Now finally, my question is: What can I do? How or where can I add the code for correct scaling without dirty manipulation of the designer file?
I have already tried to simply put these two lines for every container in the constructor after the InitializeComponent() method call, but at this position, they don't have the desired effect.
So, maybe you have an idea how it has to be done.
Thanks in advance,
Alex
I've finally found a way to solve the problem. It isn't really what I intended originally, but it has the same effect.
The concerning two properties don't show in the designer gui, so why not make them appear? Therefore I created a custom control and added some attributes to both scaling properties, so that they appear in the designer.
public class ScalableSplitContainer : SplitContainer
{
[Browsable(true)]
[EditorBrowsable(EditorBrowsableState.Always)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[Bindable(true)]
public new AutoScaleMode AutoScaleMode
{
get { return base.AutoScaleMode; }
set { base.AutoScaleMode = value; }
}
[Browsable(true)]
[EditorBrowsable(EditorBrowsableState.Always)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[Bindable(true)]
public new SizeF AutoScaleDimensions
{
get { return base.AutoScaleDimensions; }
set { base.AutoScaleDimensions = value; }
}
}
Using this specialized SplitContainer, scaling behaviour can easily be set in the gui and the code lines are included in the generated designer file.
actually i am developing a universal app for Windows and Windows Phone.
Within that app i am using dependency properties to assign data to properties of custom user controls in XAML. The problem is that the compiler says he is not able to find the property were i would like to bind data to.
The button definition looks like the following.
public sealed partial class RulerButton : UserControl
{
public static readonly DependencyProperty BackendProperty =
DependencyProperty.Register("Backend", typeof(GlobalData),
typeof(RulerButton), new PropertyMetadata(null));
public GlobalData Backend
{
get { return (GlobalData)GetValue(BackendProperty); }
set { SetValue(BackendProperty, value); }
}
public RulerButton()
{
this.InitializeComponent();
}
}
I use this button within my main page like this.
<btn:RulerButton Backend="{Binding ElementName=root, Path=BackendSource}"/>
Then the compiler says Unknown Member "Backend" in Element "RulerButton".
If have used the same approach earlier in other projects (Normal WPF-Windows applications) and it worked well. So i think the problem is related to universal app projects.
All other questions i have found could not solve my problem.
I would be appreciated if someone could give me a hint.
greets
Edit
Well i actually have solved the problem. But i think it is very curious. Beside the RulerButton i have many other controls where i added the same dependency properties. On some of them i did not add the normal property Backend yet. Cause i first wanted to make the RulerButton work. After completing these controls so that each of them has a BackendProperty and Backend attribute, all errors were gone.
anyway thanks for your help guys
Well i actually have solved the problem. But i think it is very curious. Beside the RulerButton i have many other controls where i added the same dependency properties. On some of them i did not add the normal property Backend yet. Cause i first wanted to make the RulerButton work. After completing these controls so that each of them has a BackendProperty and Backend attribute, all errors were gone.
I'm just designing a settings form for my app, nothing too fancy, It's a small app. I'm just wondering what controls are good for this? at the moment I'm using labels and textboxes and listboxes, but It's just looking crap and awkward, Is there some orthodox way to do this? Is is more horrible attempt at UI design.
You can produce some really intuitive, aesthetic interfaces with the most primative controls and a dash of creativity or inspiration. Here's a settings UI I created recently:
General Tips
A nice choice of font goes a long way. My personal favorite at the moment is Segoe UI.
Position controls using the designer rulers so that they are all relative of one another. Be consistent with your positioning too; don't position a caption above a TextBox for one field and besides the TextBox for another.
Try and find a nice size for your controls, small controls are hard to use and large controls look very amateur.
I think that setting the Form's Maximize property to false and changing the FormBorderStyle property to FixedSingle works well with small, fixed forms.
It's a good idea to get inspired. Take a look at some other projects of a similar caliber to yours and see how they position their UI.
For something quick-and-dirty, create a class that is a Model of your application's settings, like so:
public class ApplicationSettings {
public String YourName { get; set; }
public Color BackgroundColor { get; set; }
}
Then use that with a PropertyGrid control:
ApplicationSettings settings = new ApplicationSettings();
LoadSettingsFromDB( settings );
propertyGrid.SelectedObject = settings;
After the user hits OK, just persist. The property values of your settings instance will be updated.
You can also use the PropertyGrid with the VS IDE-generated AppSettings feature.