Textbox has Clear and GetSpellingErrors methods etc.
Is it possible for me to have something like < TextBox Clear={binding...} />?
I am aware Clear is not an "Dependency" anything. I'm authoring an usercontrol. I can add the DependencyProperty, DependencyObject as needed. I just want to know how to bind a method to the VM.
PS I don't need alternatives for Clear, I know I can set the property to string.empty.
Turns out you can use ICommand and create it like any other DependencyProperty.
public static readonly DependencyProperty CancelCommandProperty = DependencyProperty.Register("CancelCommand", typeof(ICommand), typeof(AddressUserControl), new PropertyMetadata());
[BindableAttribute(true)]
public ICommand CancelCommand { get { return (ICommand)GetValue(CancelCommandProperty); } set { SetValue(CancelCommandProperty, value); } }
The only problem I still have is I need this to be a read-only binding obviously.
Tried
DependencyProperty.RegisterReadOnly(...)
but there appears to be a bug with ReadOnly DependencyProperty https://connect.microsoft.com/VisualStudio/feedback/details/540833/onewaytosource-binding-from-a-readonly-dependency-property
Related
If I create a custom control like this:
public class MyControl : ContentControl
{
public static readonly DependencyProperty ItemsProperty =
DependencyProperty.Register(
"Items",
typeof(ObservableCollection<object>),
typeof(MyControl),
new PropertyMetadata(null));
public MyControl()
{
// Setup a default value to empty collection
// so users of MyControl can call MyControl.Items.Add()
Items = new ObservableCollection<object>();
}
public ObservableCollection<object> Items
{
get { return (ObservableCollection<object>)GetValue(ItemsProperty); }
set { SetValue(ItemsProperty, value); }
}
}
And then allow the user to bind to it in Xaml like this:
<DataTemplate>
<MyControl Items="{Binding ItemsOnViewModel}"/>
</DataTemplate>
Then the binding never works! This is due to the Dependency Property Precedence, which puts CLR Set values above Template bindings!
So, I understand why this isn't working, but I wonder if there is a solution. Is it possible to provide a default value of ItemsProperty to new ObservableCollection for lazy consumers of MyControl that just want to add Items programmatically, while allowing MVVM power-users of My Control to bind to the same property via a DataTemplate?
This is for Silverlight & WPF. DynamicResource setter in a style seemed like a solution but that won't work for Silverlight :(
Update:
I can confirm SetCurrentValue(ItemsProperty, new ObservableCollection<object>()); does exactly what I want - in WPF. It writes the default value, but it can be overridden by template-bindings. Can anyone suggest a Silverlight equivalent? Easier said than done! :s
Another Update:
Apparently you can simulate SetCurrentValue in .NET3.5 using value coercion, and you can simulate value coercion in Silverlight using these techniques. Perhaps there is a (long-winded) workaround here.
SetCurrentValue workaround for .NET3.5 using Value Coercion
Value Coercion workaround for Silverlight
Can't you just specify the default property of the dependency property:
public static readonly DependencyProperty ItemsProperty = DependencyProperty.Register(
"Items",
typeof(ObservableCollection<object>),
typeof(CaseDetailControl),
new PropertyMetadata(new ObservableCollection<object>()));
or am I missing what you are after?
Edit:
ah... in that case how about checking for null on the getter?:
public ObservableCollection<object> Items
{
get
{
if ((ObservableCollection<object>)GetValue(ItemsProperty) == null)
{
this.SetValue(ItemsProperty, new ObservableCollection<object>());
}
return (ObservableCollection<object>)GetValue(ItemsProperty);
}
set
{
this.SetValue(ItemsProperty, value);
}
}
When ObservableCollection properties misbehave, I try throwing out assignments to that property. I find that the references don't translate right and bindings get lost, somehow. As a result, I avoid actually setting ObservableCollection properties (preferring, instead, to clear the existing property and add elements to it). This becomes really sloppy with a DependencyProperty because you're going to call your getter multiple times in your setter. You might want to consider using INotifyPropertyChanged instead. Anyway, here's what it'd look like:
EDIT: Blatantly stole the getter from SteveL's answer. I reworked it a touch so that you only have a single call to GetValue, is all. Good work around.
public ObservableCollection<object> Items
{
get
{
ObservableCollection<object> coll = (ObservableCollection<object>)GetValue(ItemsProperty);
if (coll == null)
{
coll = new ObservableCollection<object>();
this.SetValue(ItemsProperty, coll);
}
return coll;
}
set
{
ObservableCollection<object> coll = Items;
coll.Clear();
foreach(var item in value)
coll.Add(item);
}
}
Note that this is depending on your default to set correctly. That means changing the static ItemsProperty default to be a new ObservableCollection of the correct type (i.e. new PropertyMetadata(new ObservableCollection()). You'll also have to remove that setter in the constructor. And note, I've no idea if that'll actually work. If not, you'll want to move to using INotifyPropertyChanged for sure...
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'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"/>
I have a two userControls (IconUserControl & DisplayUserControl), I'm having a problem with binding dependency properties, here's some detail:
IconUserControl has a bool DP of IsDisplayShown
DisplayUserControl has a bool DP of IsDisplayShown
In the XAML I have:
<local:DisplayUserControl
x:Name="DisplayUserControl"
IsDisplayShown="{Binding ElementName=IconUserControl, Path=IsDisplayShown, Converter={StaticResource DummyConverter}}" />
<local:IconUserControl
x:Name="IconUserControl" />
When IconUserControl.IsDisplayShown is set to true, I can see in the DummyConverter this value getting passed, but it never sets DisplayUserControl.IsDisplayShown.
However, if in the codebehind for the View I set DisplayUserControl.IsDisplayShown = true;, then it works fine.
I have the DataContext for both UserControls set to "this" in the constructor. I've tried to fiddle with the "Mode" property of the binding.
*Note: DummyConverter just returns the value, I only have this to confirm that the Binding is trying to work.
What am I doing wrong?
Edit:
Here's the two DPs:
public bool IsDisplayShown
{
get { return (bool)GetValue(IsDisplayShownProperty); }
set { SetValue(IsDisplayShownProperty, value); }
}
public static readonly DependencyProperty IsDisplayShownProperty =
DependencyProperty.Register("IsDisplayShown", typeof(bool), typeof(IconUserControl), new UIPropertyMetadata(false));
public bool IsDisplayShown
{
get { return (bool)GetValue(IsDisplayShownProperty); }
set
{
if (value)
ShowOpenItems();
else
HideOpenItems();
SetValue(IsDisplayShownProperty, value);
}
}
public static readonly DependencyProperty IsDisplayShownProperty=
DependencyProperty.Register("IsDisplayShown", typeof(bool), typeof(DisplayUserControl), new UIPropertyMetadata(false));
This should help you, but probably won't solve the whole problem. It is a good place to start, though. Adding this code will cause debugging info for the binding to dump to your Debug window in Visual Studio.
add this namespace to your xaml....
xmlns:diagnostics="clr-namespace:System.Diagnostics;assembly=WindowsBase"
then, your binding, add this:
diagnostics:PresentationTraceSources.TraceLevel=High
check Bea Stollnitz article for more information
That just doesn't make sense =) Should work =)
Did you try to set Mode=TwoWay in the binding?
Are you sure you got the DP definition right? Can you add them to the post?
I've got a custom control which has a DependencyProperty MyAnimal - I'm binding an Animal Property on my ViewModel to the MyAnimal DependencyProperty.
I've stuck a TextBox on the Control so I can trigger an Event - whenever I trigger the event the MyAnimal property has been set - however if I put a break point on the Setter of the MyAnimal property it never gets fired!
I guess I'm missing something fundamental about WPF Dependency Properties/Binding?!
And so my question is, if I can't use the Setter how can I find out when its been set? If I put if I put a break point after InitializeComponent() its null and I had a look to see if theres an Event a can hook up to - DatabindingFinished or similar? but can't see what it would be ...
Can anyone assist please?
Thanks,
Andy
public partial class ControlStrip
{
public ControlStrip()
{
InitializeComponent();
}
public Animal MyAnimal
{
get
{
return (Animal)GetValue(MyAnimalProperty);
}
set
{
SetValue(MyAnimalProperty, value);
}
}
public static readonly DependencyProperty MyAnimalProperty =
DependencyProperty.RegisterAttached("MyAnimal", typeof (Animal), typeof (ControlStrip));
private void TextBox_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
{
var myAnimal = MyAnimal;
MessageBox.Show(myAnimal.Name);
}
}
The setter methods are never called by the runtime. They go directly to the DependencyProperty. You will need to add an additional argument to your call to RegisterAttached(). There you can add a PropertyChangedCallback.
Here is some sample code:
public static readonly DependencyProperty MyAnimalProperty =
DependencyProperty.RegisterAttached("MyAnimal", typeof (Animal), typeof (ControlStrip), new PropertyMetadata(AnimalChanged));
private static void AnimalChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
// Do work here
}
The setter is only there for your use - you actually can leave the property off entirely, since DataBinding uses the actual DependencyProperty itself, not the CLR property.
If you need to see when the property changes, you will need to specify PropertyMetadata on your dependency property, and provide a PropertyChangedCallback.
For details, I recommend reading Dependency Property Metadata.