Пользовательский элемент управления 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);
Другие вопросы по тегам