Problem with Binding Dependency Property on a UserControl - wpf

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?

Related

Binding or execute control.method in mvvm

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

WPF dependency property precedence & reference type Default Values

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...

How can I get databinding debug information in MVVM/Prism?

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()

Why does my UI not update to reflect the data I have bound to it?

I've bound the visibility of some buttons to a bool, but when the bool changes, the button's visibility does not change. Why could this be?
The boolean is set up as such:
public static readonly DependencyProperty editModeToggle = DependencyProperty.Register("editMode", typeof(bool), typeof(Window));
public bool EditMode
{
get { return(bool)GetValue(editModeToggle); }
set { SetValue(editModeToggle, value); }
}
I'm pretty sure the binding isn't at fault.
[Note: I have set up a Converter that works and the binding works. The visibility just doesn't change when I change from true to false or vice versa]
Binding:
<Button Content="Test" Visibility="{Binding ElementName=mainWindow, Path=EditMode, Converter={StaticResource BooltoVisibilityConverter}/>
There are a few things you need to check when a binding does not work as expected:
Does the bool property notify change using
INotifyPropertyChanged?
Do you use a converter to convert from
bool to Visibility?
Do you see any binding errors in output
window?
Have you tried putting a breakpoint on binding in xaml
or setter in bool property?
As you have mentioned in your comment, you have not implemented INotifyPropertyChanged interface.
The need to implement the interface is whenever value of the property in ViewModel changes, there has be be a way for binding to know that. So, after implementing INotifyPropertyChanged, for each property, you raise the PropertyChanged event with the property name in it. That way, the binding knows that value of the property has changed.
There are lots of articles online. Here is one to get you started: INotifyPropertyChanged and WPF
Dependency Property registration is not correct -
public static readonly DependencyProperty editModeToggle =
DependencyProperty.Register("editMode", typeof(bool), typeof(Window));
It should be-
public static readonly DependencyProperty editModeToggle =
DependencyProperty.Register("EditMode", typeof(bool), typeof(Window));
Notice the spelling of property - 'E' should be capital since its case sensitive and your property name is EditMode not editMode.
In this case you don't need point 1 from decyclone list since you are using a dependency property. I think that you should add Mode=TwoWay in binding if you don't have it, that will solve it.

Silverlight data binding to parent user control's properties with using MVVM in both controls

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)

Resources