I am learning WPF and am trying to create my first UserControl. My UserControl consists of
StackPanel
StackPanel contains a Label and TextBox
I am trying to create two Dependency Properties
Text for the Label
Orientation for the StackPanel - The orientation will affect the position of the Label and TextBox effectively
I have successfully created a Text dependency property and bind it to my UserControls . But when I created the Orientation property, I seem to get following error in get property
The as operator must be used with a reference type or nullable type ('System.Windows.Controls.Orientation' is a non-nullable value type)
public static DependencyProperty OrientationProperty = DependencyProperty.Register("Orientation", typeof(System.Windows.Controls.Orientation), typeof(MyControl), new PropertyMetadata((System.Windows.Controls.Orientation)(Orientation.Horizontal)));
public Orientation Orientation
{
get { return GetValue(OrientationProperty) as System.Windows.Controls.Orientation; }
set { SetValue(OrientationProperty, value); }
}
Appreciate your help.
Edit:
I changed the code as below and it seem to work as expected. But is this the correct way to solve the problem?
public Orientation Orientation
{
get
{
Orientation? o = GetValue(OrientationProperty) as System.Windows.Controls.Orientation?;
if (o.HasValue)
{
return (System.Windows.Controls.Orientation)o.Value;
}
else
{
return Orientation.Horizontal;
}
}
set { SetValue(OrientationProperty, value); }
}
The error message says it all. The as operator can only be used with a Type that is nullable (reference type, or Nullable<T>), because it will return either the value cast, or null.
What you're trying to use it on is an enumeration.
Just use a regular cast:
get { return (System.Windows.Controls.Orientation) GetValue(OrientationProperty); }
Reasons why:
You define a default value in your DependencyProperty.Register call, eliminating any default null value
Your DependencyProperty is typeof(Orientation), which doesn't allow for nulls
Your class's property definition is Orientation, which doesn't allow for nulls
Any attempt to set an invalid value via direct calls to SetValue(OrientationProperty, null) will receive an exception, so your property getter won't ever see a null value even by a naughty user of it.
Related
I have a custom control and want to bind a user defined margin. In the client code where
I try to use it, it shows an error. It says -
"'0}'string cannot be converted to Length"
public static readonly DependencyProperty MarginProperty =
DependencyProperty.Register("Margin", typeof (Thickness), typeof
(TestControl), new PropertyMetadata(default(Thickness)));
public Thickness Margin
{
get { return (Thickness) GetValue(MarginProperty); }
set { SetValue(MarginProperty, value); }
}
Is there any issue with my dependency property?
Thanks & Regads
There is a Margin`property of any FrameworkElement already, what are you trying to achieve creating a dep property with the same name and same type?
I have a simple problem that I just cant find a good solution for.
I have a textbox bound to a double property value. The user can enter values into the textbox, but I only want to allow values between 0 and 100. I would like to show a red box around the textbox if an invalid value is entered while the textbox still has focus (UpdateSourceTrigger="PropertyChanged"). Should the user click away from the textbox, I want to clamp the value using a value converter on UpdateSourceTrigger="LostFocus".
Its easy to do either the validation rule or the converter, but I can not combine them as I want the validation to trigger on UpdateSourceTrigger="PropertyChanged" and the converter should trigger on UpdateSourceTrigger="LostFocus". Unfortunately I can only choose either one or the other when setting up the binding on my TextBox.Text.
Any good ideas about how I could implement this functionality?
Thank you
/Peter
That's an interesting question. I'm not sure I have a complete solution, but I'd like to throw out a couple ideas.
What do you think of creating a new class that derives from TextBox? It could have two dependency properties, MinValue and MaxValue. Then it could override OnLostFocus. (Disclaimer: I haven't tested the following code.)
public class NumericTextBox : TextBox
{
public static readonly DependencyProperty MinValueProperty =
DependencyProperty.Register("MinValue", typeof(double), typeof(NumericTextBox), new UIPropertyMetadata(Double.MinValue));
public static readonly DependencyProperty MaxValueProperty =
DependencyProperty.Register("MaxValue", typeof(double), typeof(NumericTextBox), new UIPropertyMetadata(Double.MaxValue));
public double MinValue
{
get { return (double)GetValue(MinValueProperty); }
set { SetValue(MinValueProperty, value); }
}
public double MaxValue
{
get { return (double)GetValue(MaxValueProperty); }
set { SetValue(MaxValueProperty, value); }
}
protected override void OnLostFocus(System.Windows.RoutedEventArgs e)
{
base.OnLostFocus(e);
double value = 0;
// Parse text.
if (Double.TryParse(this.Text, out value))
{
// Make sure the value is within the acceptable range.
value = Math.Max(value, this.MinValue);
value = Math.Min(value, this.MaxValue);
}
// Set the text.
this.Text = value.ToString();
}
}
This would eliminate the need for a converter, and your binding can use UpdateSourceTrigger=PropertyChanged to support your validation rule.
My suggestion admittedly has its drawbacks.
This approach would require you to have validation-related code in two places, and they'd need to match. (Maybe you could override OnTextChanged too, and set the red border there instead.)
This approach requires you to put rules in the view layer rather than in business objects, which you may or may not find acceptable.
I have a WPF application where I'm using dependency properties in codebehind which I want to set via XAML declarations.
e.g.
<l:SelectControl StateType="A" Text="Hello"/>
So in this example I have a UserControl called SelectControl, which has a property called StateType which manipulate some other properties in it's setter.
To help illustrate the problem, I've put another property called Text in the example, read on and I'll explain further.
Codebehind excerpt...
public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(String), typeof(SelectControl));
public String Text
{
get { return (String)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public static readonly DependencyProperty StateTypeProperty = DependencyProperty.Register("StateType", typeof(String), typeof(SelectControl));
public String StateType
{
get { return (String)GetValue(StateTypeProperty) }
set
{
switch (value)
{
case "A":
AnotherPropertyBoolean = true;
break;
case "B":
AnotherPropertyBoolean = false;
break;
default:
// this is only an example...
}
}
}
Now, if I set a breakpoint on the setter (for either StateType or Text), it turns out it's never executed.
However values declared for Text, i.e. "Hello" appears in it's data bound TextBox, and of course it I bind another text control to StateType's value I can see that too.
Does anyone know what's happening?
The "CLR-wrappers" for dependency properties only get called when done through code. XAML depends on the name specified in the DependencyProperty.Register(...) call. So, instead of "extending" the logic of the setter for your dependency property like you did above, just put your custom logic in a PropertyChangedCallback function.
I am new to WPF so after reading for a while I deduce that my problem needs to be handled with this pattern: DependencyProperty.
I want my ToggleButton to have another boolean property.
My problem is where should I assign this property, and how? Inside the object that is bound to the ToggleButton?
Let's say I have a class cell (which is bound to this Button) that when clicked I want that from this point on, it would hold new face with trigger on.
My new property will be:
bool wasClick
Can someone explain to me how I should write it and tell me more about this new concept?
EDIT:
The main topic is where should I define it so I want it asoocited to a Button but where should I write the code. Lets say I have a class that is bound to a Button. Should I write:
public static readonly DependencyProperty IsSpinningProperty =
DependencyProperty.Register(
... "IsSpinning", typeof(Boolean),
in this class or should I write it in my view model? If so, where and how?
As the name implies (kind of poorly), a dependency property is a property whose value can depend on something else. Generally, this means a property whose value gets determined automatically (and dynamically) by the WPF framework under certain conditions. The most common conditions are:
The property has a default value, or inherits its value from an ancestor in the visual tree. In this case, the property's value is determined without it ever being set.
The property is the target of data binding.
The property's value is set by an animation.
Not all properties whose value gets set by the WPF framework need to be dependency properties. Any CLR property with a public getter and setter can be the source of a two-way data binding.
In your case, it sounds like you don't really need a dependency property, not if you're using a view model. You could just do this (assuming that you've implemented property-change notification in your class):
private bool _IsChecked;
public bool IsChecked
{
get { return _IsChecked; } }
set
{
if (value == _IsChecked)
{
return;
}
_IsChecked = value;
WasChecked = WasChecked || value;
OnPropertyChanged("IsChecked");
}
}
private bool _WasChecked;
public bool WasChecked
{
get { return _WasChecked; }
private set
{
if (value == _WasChecked)
{
return;
}
_WasChecked = value;
OnPropertyChanged("WasChecked");
}
}
I've put together a WPF application using ObservableCollection and Dependency Properties which is cool because I just have to add an item to the ObservableCollection and it shows up automatically, e.g. I display the objects in the collection as boxes on the screen in a wrappanel, each box showing its Title.
So then I wanted to have each item show not only its Title plus a prefix or suffix, but the Dependency Object property doesn't even seem to be used. I can put a break point on it and it is never reached.
Can anyone enlighten me why, if I add text to my outgoing property, that that text is never seen? I have read that the value is actually "stored not in the object but in WPF" but I don't understand what that means.
Why is the text this text will NOT be seen never output by the dependency object?
public class ApplicationItem : DependencyObject
{
public string Title
{
get
{
return (string)GetValue("this text will NOT be seen: " + TitleProperty);
}
set
{
SetValue(TitleProperty, "this text will be seen: " + value);
}
}
}
TitleProperty is not a normal property but a dependency property so if you want to retrieve the value of your TitleProperty you have to do :
var title = (string)GetValue(TitleProperty);
In WPF guideline, the public property to access a Dependency Property is not called by WPF and the binding engine (not necessary). This public property is only used by your code behind. So you MUST not add code logic inside your public property.
But you can use a FrameworkPropertyMetadata when you register your DP and provide a CoerceValueCallback to change the setted value.
You can also use a IValueConverter with your binding.
I got this to work for me:
public string Title
{
get
{
string value = (string)GetValue(TitleProperty);
return value + " postfix";
}
set
{
SetValue(TitleProperty, "Prefix " + value);
}
}
Is there a reason why you are attempting to modify the value when retrieving it rather than just modifying it when the value is set?