Пользовательский элемент управления WPF, проблема DependencyProperty
Я получил тестовый код с пользовательским элементом управления:
/// <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();
}
}
Ничего особенного в коде XAML:
<UserControl ...>
<Grid DataContext="{Binding}">
</Grid>
</UserControl>
Код в моей модели просмотра:
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);
}
}
}
Код в MainWondow.XAML.cs:
public MainWindow()
{
InitializeComponent();
var viewModel = new ViewModel();
DataContext = viewModel;
viewModel.LastName = "asdf";
viewModel.LastName = "56udfh";
viewModel.LastName = "09ualkja";
}
Код MainWindow.XAML:
<Window...>
<Grid>
<CustomControlTest:UCTest LastName="{Binding LastName}"/>
</Grid>
</Window>
Я установил контрольные точки и установил "Когда попал". Выходные данные (ниже) показывают, что свойство вызывается только для последнего выполнения "LastName". Я ожидаю, что он будет вызывать изменения при каждом выполнении... Есть идеи, почему?
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
Спасибо,
PS, это дополнительный вопрос к моему предыдущему посту. Мысль я бы начал новую, потому что реальная проблема не связана с моим первоначальным постом.:)
1 ответ
Ваш элемент управления не загружен в конструктор MainWindow, поэтому привязка еще не установлена. Вы можете проверить это, установив точку останова в последнем назначении, в обработчике изменений и в конце конструктора. Вы увидите, что этот конструктор завершит работу, пока не изменится свойство UCTest.
Вы можете решить эту проблему, отложив назначения с помощью Dispatcher:
this.Dispatcher.BeginInvoke((Action)(() =>
{
viewModel.LastName = "asdf";
viewModel.LastName = "56udfh";
viewModel.LastName = "09ualkja";
}),
DispatcherPriority.DataBind);