How to set DefaultText of TextBox in Windows Forms application? - winforms

From MSDN entry for Control.ResetText():
Resets the Text property to its default value.
Stupid question, but I can't find where I can set this "default value". When I invoke ResetText() on TextBox all text is simply cleared.

The default value used by ResetText in the TextBoxcontrol is not configurable and it happens to be the string.Empty so that's why when you invoke the method the text is cleared.
However, since the ResetText method is virtual you can do the following:
class MyTextBox : TextBox
{
public override void ResetText()
{
this.Text = "MyDefaultText";
}
}
Now, you just need to use your MyTextBox instead of the TextBox control. This is of course complicating things just for the sake of setting the Text property, so you are better of by assigning your default text directly to the Text property if you have no requirements to support a default value specifically through the use of ResetText.

That method is used within the designers. So unless you are not writing a designer with this control you need not worry about it. Runtime default value is empty string.

Related

How Do I Stop Visual Studio from Generating property setting for the controls in designer?

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.

Stop CommandBindings being serialised in UserControl

I have a user control that programmatically sets up its command bindings and content.
I also serialise this control to XAML. I do not want the content or bindings to be serialised since I set these up. Content is taken care of by overriding:
public virtual bool ShouldSerializeContent()
And I was pleased to see an equivalent for command bindings:
public bool ShouldSerializeCommandBindings()
However, this function is not virtual, and hiding it by specifying new in my implementation appears to do nothing? This does appear to be the recommended way to use it according to this MS page:
http://msdn.microsoft.com/en-us/library/53b8022e(v=vs.85).aspx
I have also tried shadowing the CommandBindings property and using [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)], but this just breaks my bindings.
Can anyone show me the correct way? Is this a bug?
Aha, nevermind I've sorted it. The trick is indeed to shadow the property, but I wasn't providing any implementation. The following works to turn off serialization:
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public CommandBindingCollection CommandBindings
{
get
{
return base.CommandBindings;
}
}

Silverlight - add ValueConverter to Binding object in custom control

I'm building a custom control in Silverlight, extending TextBox. The purpose of the control is to provide a watermark logic (default text, typically used in search boxes). I managed that, when accessing the Text property, it will return string.Empty if Text == Watermark. Indeed, you don't want to consider something like "Enter name here" as a relevant value. When it comes to TwoWay databinding, things get more complicated.
I created a ValueConverter, that takes as parameter the watermark and returns string.Empty if Text == Watermark, Text otherwise. I want the control to be very ease to use, so it would be cool if the client code wouldn't have to specify each time that converter when binding to the Text property. Instead, the converter would be plugged inside the custom control, on the binding object related to the Text property.
I tried the following code, but it crashes because the binding object cannot be modified once it has been assigned. I tried that code in the Load() and OnApplyTemplate() events.
var watermarkedTextBox = (WatermarkedTextBox)dependencyObject;
var textBindingExpression = watermarkedTextBox.GetBindingExpression(TextProperty);
if (textBindingExpression != null)
{
var textBinding = textBindingExpression.ParentBinding;
textBinding.Converter = new WatermarkConverter();
textBinding.ConverterParameter = watermarkedTextBox.Watermark;
watermarkedTextBox.SetBinding(TextProperty, textBinding);
}
So I need to intercept the binding object at the right time (where it's still allowed to modify it). Any ideas ?
Thanks in advance,
Thibaut
All right, discussed this with colleagues, found the optimal solution.
The watermark is defined in the ControlTemplate of the custom control. It's a TextBlock added in the TextBox, hidden on focus, shown if text is empty. Code is much better like that :
No need to play with the Text property and change it under certain conditions to change it to watermark, or change it to string.Empty so the watermark text is never returned (was error prone)
Watermark text style can be directly template bound (TemplateBinding), so it's great, without any C# code, client will be able to customize the appearance of the watermark : color, italicize and more
Offers new possibilities (image watermark textbox almost for free)
See you ;)
I haven't tried it yet but the Silverlight 4 Textbox has a Watermark property.

S/L 4 & IDataErrorInfo - How to force re-validation of a control (when a related control is touched)

I have two controls bound to properties MinCartValue and MaxCartValue. MinCartValue must be less than MaxCartValue. To achieve this validation I have implemented the the IDataErrorInfo interface, and run the above check in the this[columnName] method if either MinCartValue or MaxCartValue are touched. ValidatesOnDataErrors=True is set in the binding of both controls.
The validation works correctly, highlighting each control when a change to its property value violates the rule. The problem is that once a control is flagged as invalid, if the user corrects the problem by altering the other control's value, the first control remains flagged as invalid. This is understandable because the IDataErrorInfo method was not doing validation on the first control's property.
So what I need is a way to force property #1 to be re-validated (or a way to clear the invalid state) when property #2 is validated, and vice versa. I have tried calling RaisePropertyChanged within my this[columnName] method but it does nothing. Also tried setting the property to its own value to try to trick it to validate itself, but again nothing happens.
Thanks
I would recommend looking at the INotifyDataErrorInfo interface (introduced in Silverlight 4). It's able to async-notify if properties become invalid, so I think the framework is better about respecting this across many properties instead of expecting that the property currently being changed is the only one whose validity may be changing.
I had two DateTime properties (DateFrom and DateTo) that needed to be validated against each other. In the setters for these properties I just raised a PropertyChanged event for both DateTo and DateFrom. Worked like a charm.
I'm not sure if I'm understanding your problem exactly, but perhaps this may help. Providing some example XAML and the binding property code would help.
It sounds like an issue of your code depending on the default UpdateSourceTrigger, which in the case of TextBox controls is their focus/unfocus. You can set in the XAML the UpdateSourceTrigger attribute by adding UpdateSourceTrigger=Explicit to your binding where your validation occurs. Then in each TextBox (MinCartValue, MaxCartValue), add an event handler to the TextChanged event.
In the code-behind in the event handler, you can do something like this:
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
TheTextBox.GetBindingExpression(TextBox.TextProperty).UpdateSource();
}
TheTextBox in this case would be one of your cart controls. The UpdateSource() method is a way to manually update the binding value, which should trigger your validation. This method provides away to tie into a trigger to update values and raising properties have changed outside of the default scope (using text changed intead of focus and unfocus on TextBox in this instance).
Here's how I solved it. Let's say Property1 and Property2 are codependent. I'm not familiar with MVVM (yet), but you're probably extending your entity class to implement IDataErrorInfo. In this case you can also extend On[Property]Changed method and report change in codependent property:
partial class YourEntity : IDataErrorInfo
{
public string this[string columnName]
{
//Your validation logic
}
public string Error
{
//WPF doesn't use it anyway
get { return string.Empty; }
}
partial void OnProperty1Changed()
{
OnPropertyChanging("Property2");
OnPropertyChanged("Property2");
}
partial void OnProperty2Changed()
{
OnPropertyChanging("Property1");
OnPropertyChanged("Property1");
}
}
In this case the update in either one of this properties makes both bound controls re-evaluate themselves.
EDIT2: It appears that you should use OnPropertyChang* instead of ReportPropertyChang*. ReportPropertyChanged will notify the entity framework that there are pending changes in the model, but in fact all you're trying to do is inform the view. You don't want to update the database with the property that didn't really change. ReportPropertyChang* will also fail on computed fields that have no mappings in the database.
EDIT1: Found out that it's essential to call ReportPropertyChanging before ReportPropertyChanged.

How to stop a WPF binding from ignoring the PropertyChanged event that it caused?

I have a TextBox bound to a ViewModel's Text property with the following setup:
Xaml
<TextBox Text="{Binding Text}"/>
C#
public class ViewModel : INotifyPropertyChanged
{
public string Text
{
get
{
return m_Text;
}
set
{
if (String.Equals(m_Text, value))
{
return;
}
m_Text = value.ToLower();
RaisePropertyChanged("Text");
}
}
// Snip
}
When I type some stuff in to the TextBox it successfully sets the Text property on the ViewModel. The problem is that WPF ignores the property changed event that is raised by it's own update. This results in the user not seeing the text they typed converted to lowercase.
How can I change this behaviour so that the TextBox updates with lowercase text?
Note: this is just an example I have used to illustrate the problem of WPF ignoring events. I'm not really interested in converting strings to lowercase or any issues with String.Equals(string, string).
You can achieve this by raising the event in a seperate dispatcher call using Dispatcher.BeginInvoke
Define a delegate:
private delegate void RaisePropertyChangedDelegate(string property);
Then use the following to raise the event
Dispatcher.CurrentDispatcher.BeginInvoke(
DispatcherPriority.Normal,
new RaisePropertyChangedDelegate(RaisePropertyChanged),
"Text");
Apparently this is fixed in WPF 4.0 in .NET Framework 4.0 released in 2010: Karl Shifflett's blog
I remember Rocky Lhotka complaining about this very behaviour on an old episode of .NET Rocks. (Searches for half an hour ...) ah, here we are. Episode 169 from March, 2006:
So if you have got a detailed Form in
Windows Forms then you bind all of
your properties to those different
text boxes and the user is typing
things into a text box and tabs off,
of course that value gets put into
your object but your object then might
change the value, may be there is some
sort of a manipulation that says all
letters must be upper case. It’s a
business rule so it goes in your
object. If you do that it won’t show
up in the UI. In other words the user
can type a, b, c, type in lower case,
tab off. The lower case a, b, c will
stay in the text box. Then later when
they change some other field, then
they will keep in mind the object to
upper case the value, right? So the
object has an uppercase a, b, c the UI
is incorrectly showing a lowercase,
the user then changes some other
control and tabs off that control, all
of a sudden the a, b, c in uppercase
shows up in the text box that they
weren’t on.
Rocky doesn't actually suggest a solution to the problem, and I'd hazard that if he hasn't worked it out maybe there's no good answer. Perhaps you need to subscribe to the PropertyChanged event on your object from the code-behind and manually refresh the binding when the property in question has changed.
ps. This isn't directly answering your question, but in the example you've given you could set the CharacterCasing on the TextBox so that it only accepts lower-case characters.
You need to force an update of the binding target (see this post on MSDN). However, this was changed/broken in WPF4, so you have to force an update on the source instead (see this post).

Resources