Ive got a test code setup with the custom control:
/// <summary>
/// Interaction logic for UCTest.xaml
/// </summary>
public partial class UCTest : UserControl
{
public static readonly DependencyProperty LastNameProperty =
DependencyProperty.Register("LastName", typeof(string), typeof(UCTest),
new PropertyMetadata("No Name", LastNameChangedCallback, LastNameCoerceCallback),
LastNameValidateCallback);
private static void LastNameChangedCallback(
DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
Console.WriteLine(e.OldValue + " " + e.NewValue);
}
private static object LastNameCoerceCallback(DependencyObject obj, object o)
{
string s = o as string;
if (s.Length > 8)
s = s.Substring(0, 8);
return s;
}
private static bool LastNameValidateCallback(object value)
{
return value != null;
}
public string LastName
{
get
{
return (string)GetValue(LastNameProperty);
}
set
{
SetValue(LastNameProperty, value);
}
}
public UCTest()
{
InitializeComponent();
}
}
Nothing fancy in the XAML code:
<UserControl ...>
<Grid DataContext="{Binding}">
</Grid>
</UserControl>
Code in my View-Model:
public class ViewModel : DependencyObject
{
public static readonly DependencyProperty LastNameProperty =
DependencyProperty.Register("LastName", typeof(string), typeof(ViewModel));
public string LastName
{
get
{
return (string)GetValue(LastNameProperty);
}
set
{
SetValue(LastNameProperty, value);
}
}
}
Code in MainWondow.XAML.cs:
public MainWindow()
{
InitializeComponent();
var viewModel = new ViewModel();
DataContext = viewModel;
viewModel.LastName = "asdf";
viewModel.LastName = "56udfh";
viewModel.LastName = "09ualkja";
}
MainWindow.XAML code:
<Window...>
<Grid>
<CustomControlTest:UCTest LastName="{Binding LastName}"/>
</Grid>
</Window>
Ive got breakpoints setup and set to "When Hit". Output (below) shows that property only called to be updated on the last execution of "LastName". I would expect it to be calling the on changed on every execute... Any ideas why?
Step into: Stepping over non-user code 'CustomControlTest.App.App'
Step into: Stepping over non-user code 'CustomControlTest.App.InitializeComponent'
Function: CustomControlTest.UCTest.LastNameValidateCallback(object), Thread: 0x1DDC Main Thread
Function: CustomControlTest.UCTest.LastNameValidateCallback(object), Thread: 0x1DDC Main Thread
Function: CustomControlTest.UCTest.LastNameValidateCallback(object), Thread: 0x1DDC Main Thread
Function: CustomControlTest.UCTest.LastNameCoerceCallback(System.Windows.DependencyObject, object), Thread: 0x1DDC Main Thread
Function: CustomControlTest.UCTest.LastNameValidateCallback(object), Thread: 0x1DDC Main Thread
Function: CustomControlTest.UCTest.LastNameValidateCallback(object), Thread: 0x1DDC Main Thread
Function: CustomControlTest.UCTest.LastNameCoerceCallback(System.Windows.DependencyObject, object), Thread: 0x1DDC Main Thread
Function: CustomControlTest.UCTest.LastNameChangedCallback(System.Windows.DependencyObject, System.Windows.DependencyPropertyChangedEventArgs), Thread: 0x1DDC Main Thread
No Name 09ualkja
Thanks,
PS, this is a follow up question to my previous post. Thought Id start a new one because the real issue is not related to my original post. : )
Your control is not loaded in the MainWindow constructor, so the Binding is not established yet. You may check this by setting breakpoint on the last assignment, in the change handler, and at the end of constructor. You'll see that constructor finishes until UCTest's property changes.
You can solve this problem by deferring assignments using Dispatcher:
this.Dispatcher.BeginInvoke((Action)(() =>
{
viewModel.LastName = "asdf";
viewModel.LastName = "56udfh";
viewModel.LastName = "09ualkja";
}),
DispatcherPriority.DataBind);
来源:https://stackoverflow.com/questions/6639237/wpf-custom-control-dependencyproperty-issue