Reputation: 479
So, I am trying to create a UserControl with some DependencyProperties so that I can reuse code. However, some properties are not being update, while others are. What is even weirder is that even for those properties that are being updated the method "set" is not being called at all.
Here is my code:
On the ViewModel:
public ICommand TestCommand = new DelegateCommand(x => MessageBox.Show("Ocorreu Evento"));
public List<string> TestList = new List<string> { "Hello","This","is","a","Test" };
On the View:
<views:CustomizedList Header="Testing"
Items="{Binding TestList}"/>
The User control view:
<StackPanel>
<Label Content="{Binding Header}" />
<ListBox ItemsSource="{Binding Items}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="Hello"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
The user control code:
public string Header
{
get { return (string)GetValue(HeaderProperty); }
set
{
MessageBox.Show("New header is " + value);
SetValue(HeaderProperty, value);
}
}
public BindingList<object> Items
{
get { return (BindingList<object>)GetValue(ItemsProperty); }
set {
SetValue(ItemsProperty, value);
Console.WriteLine("Value was set with " + value.Count + " items.");
}
}
public static readonly DependencyProperty HeaderProperty =
DependencyProperty.Register("Header", typeof(string),
typeof(ListaCustomizada));
public static readonly DependencyProperty ItemsProperty =
DependencyProperty.Register("Items", typeof(BindingList<object>),
typeof(ListaCustomizada));
The Header is showing up, but the Items are not. Not that I added some console prints to check if the methods are being called, but nothing shows up, even for the Header. I am setting the DataContext of the UserControl to be itself.
Any ideas?
EDIT:
Following @Garry Vass sugestion, I added a Callback function. The new code is:
public static readonly DependencyProperty HeaderProperty =
DependencyProperty.Register("Header", typeof(string),
typeof(ListaCustomizada), new PropertyMetadata("", ChangedCallback));
public static readonly DependencyProperty ItemsProperty =
DependencyProperty.Register("Items", typeof(BindingList<object>),
typeof(ListaCustomizada), new PropertyMetadata(new BindingList<object>(), ChangedCallback));
private static void ChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Console.WriteLine("Dependency property is now " + e.NewValue);
}
With this I can see the value of Header changing, but there's no callback happening for Items.
EDIT:
Changed the TestList to be property instead of field, an it's type to BindingList to be consistent with the data in the user control, still same results.
public BindingList<object> TestList { get; set; }
public ViewModel()
{
TestList = new BindingList<object> { "Hello", "This", "is", "a", "Test" };
}
EDIT: Testing more I found out that the error comes from the fact that the DP ont eh usercontrol is binded to a DP on the view, which is binded to the VM.
EDIT: Finally got it to work. Searching a little deeper i found this link at codeproject that explains perfectly how to create usercontrols.
Upvotes: 2
Views: 1235
Reputation: 8812
While it may seem counter-intuitive, the WPF binding engine basically ignores the setter and getter in your code and uses its own version which lies deep within the WPF plumbing. So any code you put there to intervene, or in your case, to inspect, will just lie unexecuted.
So why are they there at all? They are helpers at compile time and also give your Xaml something to connect to.
If you want to intervene or inspect what's happening with a Dependency Property, you can declare it like this...
#region MyProperty (DependencyProperty)
public int MyProperty
{
get { return (int)GetValue(MyPropertyProperty); }
set { SetValue(MyPropertyProperty, value); }
}
public static readonly DependencyProperty MyPropertyProperty =
DependencyProperty.Register("MyProperty", typeof(int), typeof(MainWindow),
new PropertyMetadata(0, ChangedCallback));
private static void ChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Console.WriteLine("Dependency property is now " + e.NewValue);
}
#endregion
This declares a Dependency Property with a Property Changed call back. WPF will invoke it whenever the property is set.
You will see the changes happening in the call back method by anchoring your debugger where the Console statement is.
Upvotes: 2