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.
Related
I declared a dependency property with FrameworkPropertyMetadataOptions.Inherits:
public static class DesignerItemStyles {
public static readonly DependencyProperty HeaderBackgroundProperty =
DependencyProperty.RegisterAttached(
"HeaderBackground", typeof(Brush), typeof(DesignerItemStyles),
new FrameworkPropertyMetadata(
Brushes.DesignerViewElementHeaderBackground,
FrameworkPropertyMetadataOptions.Inherits));
/* Below are Get & Set as usual */
}
It kind of works, but somehow not throughout the visual tree. Here is a screenshot showing ContentPresenter that inherit value from HeaderedDesignerItemChrome:
And now, a screenshot showing content of the ContentPresenter, and it does not inherit the value. Nor it is set to something else - it is a default value:
Any idea why?
Using this is not that straight forward since there are some rules that need to be followed to implement property with inheritable values. Here they are:
On parent, dependency property must be defined as attached property. You can still declare property getter/setter, but property must be attached. Here is simple declaration:
public static readonly DependencyProperty InheritedValueProperty =
DependencyProperty.RegisterAttached("InheritedValue",
typeof(int), typeof(MyClass), new FrameworkPropertyMetadata(0,
FrameworkPropertyMetadataOptions.Inherits));
public static int GetInheritedValue(DependencyObject target)
{
return (int)target.GetValue(InheritedValueProperty);
}
public static void SetInheritedValue(DependencyObject target, int value)
{
target.SetValue(InheritedValueProperty, value);
}
public int InheritedValue
{
get
{
return GetTimeSlotDuration(this);
}
set
{
SetTimeSlotDuration(this, value);
}
}
Child objects would define their instance of the property with inherited value using AddOwner. Following is the code that goes into say MyChildClass sample class:
public static readonly DependencyProperty InheritedValueProperty;
public int InheritedValue
{
get
{
return (int)GetValue(InheritedValueProperty);
}
set
{
SetValue(InheritedValueProperty, value);
}
}
static MyChildClass()
{
InheritedValueProperty =
MyClass.InheritedValueProperty.AddOwner(typeof(MyChildClass),
new FrameworkPropertyMetadata(0,
FrameworkPropertyMetadataOptions.Inherits));
}
The global default value is preserved and inheritance still works, if the single argument overload is used...
MyClass.InheritedValueProperty.AddOwner(typeof(MyChildClass));
Note that property is in child class declared as standard dependency property and that it specifies Inherit in meta-data options.
With setup like this now when MyChildClass in parented to MyClass visually or logically they will share the same property value automatically.
So technically, what you see in the Visual Tree is doing what you told it to do. It set the default value that you told it to and the inherited controls inherit from the value of the parent which is your ContentPresenter
Eliminating one of the two ContentPresenters (visible on both screenshots just above DesignerItemsPresenter) worked for me. I am inclined to believe that was a bug in WPF framework itself.
I am making my first serious foray into Prism(Unity). I have a module with a toolbar control that gets loaded (properly) into the region that it is supposed to. This toolbar is a listbox with ItemsSource databound to the ToolButtons property on its ViewModel, the constructor for which instantiates and adds three ToolButtons to the ToolButtons collection.
My ToolButton class has three custom DependencyProperties: Title (string), ButtonFace (Image), ActiveDocumentCount (int). Styling is taken care of by a resource dictionary in the module with a Style and associated ControlTemplate. I have databound the properties, but none of the values or the image are displaying (other elements in the style are however) via TemplateBinding.
I am trying to debug the databinding, but to no avail. I do not get any massages pertinent in the Output window, and the 2nd and 3rd suggestions in this blog have produced no output either. I think that if I could get the verbose (i.e. PresentationTraceSources.TraceLevel=High) output, I could figure out what is happening on the databinding front.
EDIT:
Toolbutton Class
public class ToolButton : Button
{
public ToolButton()
{
//DefaultStyleKeyProperty.OverrideMetadata(typeof(ToolButton), new FrameworkPropertyMetadata(typeof(ToolButton)));
}
public Image ButtonFace
{
get { return (Image)this.GetValue(ButtonFaceProperty); }
set { this.SetValue(ButtonFaceProperty, value); }
}
public static readonly DependencyProperty ButtonFaceProperty =
DependencyProperty.Register("ButtonFace", typeof(Image), typeof(ToolButton), new PropertyMetadata(null));
public string Title
{
get { return (string)this.GetValue(TitleProperty); }
set { this.SetValue(TitleProperty, value); }
}
public static readonly DependencyProperty TitleProperty =
DependencyProperty.Register("Title", typeof(string), typeof(ToolButton), new PropertyMetadata(""));
public int OpenRecordCount
{
get { return (int)this.GetValue(OpenRecordCountProperty); }
set { this.SetValue(OpenRecordCountProperty, value); }
}
public static readonly DependencyProperty OpenRecordCountProperty =
DependencyProperty.Register("OpenRecordCount", typeof(int), typeof(ToolButton), new PropertyMetadata(null));
}
Those DPs look ok SetValue in the CLR backed property is fine....but if you or anyone is setting a local value on those properites (e.g. by calling your CLR backed properties or DependencyObject.SetValue) then that will destroy the binding.
Related links:
http://arbel.net/2009/11/04/local-values-in-dependencyobjects/
http://blogs.msdn.com/b/vinsibal/archive/2009/05/21/the-control-local-values-bug-solution-and-new-wpf-4-0-related-apis.aspx
http://wpf.2000things.com/2010/12/06/147-use-setcurrentvalue-when-you-want-to-set-a-dependency-property-value-from-within-a-control/
Whats the difference between Dependency Property SetValue() & SetCurrentValue()
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 have two UserControls ("UserControlParentView" and "UserControlChildView") with MVVM pattern implemented in both controls. Parent control is a container for Child control and child control's property should be updated by data binding from Parent control in order to show/hide some check box inside Child control.
Parent Control Description
UserControlParentViewModel has property:
private bool isShowCheckbox = false;
public bool IsShowCheckbox
{
get { return isShowCheckbox; }
set { isShowCheckbox = value; NotifyPropertyChanged("IsShowCheckbox"); }
}
UserControlParentViewModel - how I set DataContext of Parent control:
public UserControlParentView()
{
InitializeComponent();
this.DataContext = new UserControlParentViewModel();
}
UserControlParentView contains toggle button (in XAML), bound to UserControlParentViewModel's property IsShowCheckbox
<ToggleButton Grid.Column="1" IsChecked="{Binding IsShowCheckbox, Mode=TwoWay}"></ToggleButton>
Also Parent control contains instance of child element (somewhere in XAML)
<local:UserControlChildView IsCheckBoxVisible="{Binding IsShowCheckbox}" ></local:UserControlChildView>
so property in child control should be updated when user togggle/untoggle button.
Child control contains Boolean property to be updated from parent control, but nothing happened! Breakpoint never fired!
Property in UserControlChildView that should be updated from Parent control (here I plan to make chechBox visible/hidden in code behind):
public bool IsCheckBoxVisible
{
get { return (bool)GetValue(IsCheckBoxVisibleProperty); }
set { SetValue(IsCheckBoxVisibleProperty, value); }
}
// Using a DependencyProperty as the backing store for IsCheckBoxVisible. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsCheckBoxVisibleProperty =
DependencyProperty.Register("IsCheckBoxVisible", typeof(bool), typeof(TopMenuButton), new PropertyMetadata(false));
So the question is - what I'm doing wrong? Why child's property is never updated? BTW - there is no any binding error warnings in Output window...
You don't state where you put the breakpoint "never fired!". My guess is you placing a break point in the set mutator method of the IsCheckBoxVisible property.
You are operating under the assumption that the binding on that property will at some point cause the set method to be called when assigning the value. However the Silverlight binding framework actuall calls SetValue directly. It passes to the SetValue method the value of IsCheckBoxVisibleProperty and the value to be assigned.
I can't see all your code, so I can't work out everything, but a couple of questions:
In your DependencyProperty.Register call, you specify typeof(TopMenuButton), which should be the UserControlChildView - I don't know if that is your view or not?
You don't set up a callback method for property changed. To do this you would have to define the properties for the FrameworkPropertyMetadata, before registering the depencencyProperty like so:
FrameworkPropertyMetadata metadata = new FrameworkPropertyMetadata();
metadata.PropertyChangedCallback += OnSpacePropertyChanged;
You'd then have to declare OnSpacePropertyChanged, but you can at least respond to setting the property from there.
I am pretty sure you can't bind to a dependency property on a user control in Silverlight 3. I've tried it myself 9 months ago, and attempted all sorts of things to get it to work. Eventually I read somewhere that it simply wasn't possible. I have done it in WPF, so was beating my head on it for a while, thinking it was my implementation.
So, on the surface your code looks correct but this won't help.
I thought it was slated as something to be fixed in SL4.
Are you using SL4?
Hoho!! I've got it to work!
In child control I've changed property a bit
public bool IsCheckBoxVisible
{
get { return (bool)GetValue(IsCheckBoxVisibleProperty); }
set { SetValue(IsCheckBoxVisibleProperty, value); }
}
// Using a DependencyProperty as the backing store for IsCheckBoxVisible. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsCheckBoxVisibleProperty =
DependencyProperty.Register("IsCheckBoxVisible", typeof(bool), typeof(UserControlChildView), new PropertyMetadata(false, new PropertyChangedCallback((d, dc) =>
{
var button = d as UserControlChildView;
button.CheckBoxVisibility = ((bool)dc.NewValue) ? Visibility.Visible : Visibility.Collapsed;
})));
so now I have new event subscription (see anonymous method) and it fires when in parent control IsShowCheckbox property is changed!
CheckBoxVisibility depend.property looks like this:
public Visibility CheckBoxVisibility
{
get { return (Visibility)GetValue(CheckBoxVisibilityProperty); }
set { SetValue(CheckBoxVisibilityProperty, value); }
}
// Using a DependencyProperty as the backing store for IsCheckBoxVisible. This enables animation, styling, binding, etc...
public static readonly DependencyProperty CheckBoxVisibilityProperty =
DependencyProperty.Register("CheckBoxVisibility", typeof(Visibility), typeof(UserControlChildView), new PropertyMetadata(Visibility.Collapsed));
Constructor of serControlChildView looks like:
public UserControlChildView()
{
InitializeComponent();
this.LayoutRoot.DataContext = this;
}
So seems like it works! Thank you for your help, folks!
Ok, it seems like everything worked fine and I was confused just by non-fired breakpoint.
For simplicity I've decided to remove IsCheckBoxVisible boolean depend.property from the Child control and to bind checkBox visibility in Child control directly to CheckBoxVisibility depend.property (type is Visibility).
Also in the Parent control now I have this:
<local:UserControlChildView CheckBoxVisibility="{Binding Path=CheckboxControlVisibility}"></local:UserControlChildView>
So in the Parent control now I have CheckboxControlVisibility property (type is Visibility)
I'm not quite sure if I've got the right grasp on this or not, what I've read seems to agree with what I'm trying to do, however It doesn't seem to be working.
If I add an additional owner to a dependency property of a class, whenever the orig class dp changes, the change should get propagated to the additional owner, correct?
What I have is a custom control, which I want to set a property on, and then on certain objects that are within the custom control data template inherit this property value.
public class Class1: DependencyObject{
public static readonly DependencyProperty LongDayHeadersProperty;
public bool LongDayHeaders {
get { return (bool)GetValue(LongDayHeadersProperty); }
set { SetValue(LongDayHeadersProperty, value); }
}
static Class1(){
LongDayHeadersProperty = DependencyProperty.Register("LongDayHeaders", typeof(bool), typeof(Class1),
new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.Inherits));
}
}
public class Class2: DependecyObject{
public static readonly DependencyProperty LongDayHeadersProperty;
public bool LongDayHeaders{
get{ return(bool)GetValue(LongDayHeadersProperty); }
set{ SetValue(LongDayHeadersProperty, value); }
}
static Class2(){
LongDayHeadersProperty = Class1.LongDayHeadersProperty.AddOwner(typeof(Class2));
}
}
But if I assign a DependencyPropertyDescriptor to both properties, it only fires for the Class1 and Class2 doesn't change.
Have I missed something in my understanding?
UPDATE
After some testing, I'm not even sure if my child control is considered a child control within the logical or visual tree. I think it is, but the lack of success leads me to believe otherwise.
There a many class2's which exist in an observable collection of class1. This, to me, makes them childs of class1? But even if I use RegisterAttach on class2, and set the property in class1, it doesn't seem to have any effect?
As MSDN states, the Inherits flag only works when you use RegisterAttached to create the property. You can still use the property syntax for the property.
Update
For clarity, here is how I would define the properties:
public class Class1 : FrameworkElement
{
public static readonly DependencyProperty LongDayHeadersProperty =
DependencyProperty.RegisterAttached("LongDayHeaders",
typeof(bool),
typeof(Class1),
new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.Inherits));
public bool LongDayHeaders
{
get { return (bool)GetValue(LongDayHeadersProperty); }
set { SetValue(LongDayHeadersProperty, value); }
}
}
public class Class2: FrameworkElement
{
public static readonly DependencyProperty LongDayHeadersProperty =
Class1.LongDayHeadersProperty.AddOwner(typeof(Class2));
public bool LongDayHeaders
{
get{ return(bool)GetValue(LongDayHeadersProperty); }
set{ SetValue(LongDayHeadersProperty, value); }
}
}
If you want your children to be logical children of your control, you need to call the AddLogicalChild. Also, you should expose them through the LogicalChildren property. I must also point out that both classes must derive from FrameworkElement or FrameworkContentElement, as the logical tree is only defined for these elements.
Since you are using an ObservableCollection, you would handle the collection changed events and Add/Remove the children depending on the change. Also, the LogicalChildren property can just return your collection's enumerator.
You are confusing DependencyProperties with Attached (Dependency) Properties.
A DP is for when a class wants bindable, stylable etc properties on itself. Just like .NET properties, they are scoped within their classes. You can register for a property changed event on individual objects, but not globally. TextBox.Text is an example of this. Note that Label.Text is unrelated to TextBox.Text.
An AP is for when a class wants to decorate another object with additional properties. The class that declares the AP is able to listen for property changed events on ALL instances of other objects that have this AP set. Canvas.Left is an example of this. Note that you always have to qualify this setter: <Label Text="Hi" Canvas.Left="50"/>