Язык программирования C#9 и платформа .NET5
Часть 519 из 642 Информация о книге
После запуска приложения объект анимации не сможет найти подходящую цель и сгенерируется исключение. Причина в том, что свойство
не было зарегистрировано как свойство зависимости! Чтобы устранить проблему, возвратитесь в файл кода для специального элемента управления и полностью закомментируйте текущую логику свойства (включая закрытое поддерживающее поле).CurrentNumberТеперь добавьте показанный ниже код, чтобы свойство
создавалось как свойство зависимости:CurrentNumberpublic int CurrentNumber{get => (int)GetValue(CurrentNumberProperty);set => SetValue(CurrentNumberProperty, value);}public static readonly DependencyProperty CurrentNumberProperty =DependencyProperty.Register("CurrentNumber",typeof(int),typeof(ShowNumberControl),new UIPropertyMetadata(0));Работа похожа на ту, что делалась в реализации свойства
: тем не менее, предыдущий фрагмент кода регистрирует свойство непосредственно в теле, а не в статическом конструкторе (что хорошо). Также обратите внимание, что объектHeightиспользуется для определения стандартного целочисленного значения (UIPropertyMetadata) вместо более сложного объекта0. В итоге получается простейшая версияFrameworkPropertyMetadataкак свойства зависимости.CurrentNumberДобавление процедуры проверки достоверности данных
Хотя у вас есть свойство зависимости по имени
(и исключение больше не генерируется), анимация пока еще не наблюдается. Следующей корректировкой будет указание функции, вызываемой для выполнения проверки достоверности данных. В данном примере предполагается, что нужно обеспечить нахождение значения свойстваCurrentNumberв диапазоне между 0 и 500.CurrentNumberДобавьте в метод
последний аргумент типаDependencyProperty.Register(), указывающий на метод по имениValidateValueCallback.ValidateCurrentNumberЗдесь
является делегатом, который может указывать только на методы, возвращающие типValidateValueCallbackи принимающие единственный аргумент типаbool. Экземплярobjectпредставляет присваиваемое новое значение. Реализацияobjectдолжна возвращатьValidateCurrentNumber, если входное значение находится в ожидаемом диапазоне, иtrueв противном случае:falsepublic static readonly DependencyProperty CurrentNumberProperty =DependencyProperty.Register("CurrentNumber",typeof(int),typeof(ShowNumberControl),new UIPropertyMetadata(100),new ValidateValueCallback(ValidateCurrentNumber));// Простое бизнес-правило: значение должно находиться// в диапазоне между 0 и 500.public static bool ValidateCurrentNumber(object value) =>Convert.ToInt32(value) >= 0 && Convert.ToInt32(value) <= 500;Реагирование на изменение свойства
Итак, допустимое число уже есть, но анимация по-прежнему отсутствует. Последнее изменение, которое потребуется внести — передать во втором аргументе конструктора
объектUIPropertyMrtadata. Данный делегат может указывать на любой метод, принимающийPropertyChangedCallbackв первом параметре иDependencyObjectво втором. Модифицируйте код следующим образом:DependencyPropertyChangeEventArgs<b>// Обратите внимание на второй параметр конструктора UIPropertyMetadata.</b>public static readonly DependencyProperty CurrentNumberProperty =DependencyProperty.Register("CurrentNumber", typeof(int),typeof(ShowNumberControl),new UIPropertyMetadata(100,new PropertyChangedCallback(CurrentNumberChanged)),new ValidateValueCallback(ValidateCurrentNumber));Конечной целью внутри метода
будет изменение свойстваCurrentNumberChamged()объектаContentна новое значение, присвоенное свойствуLabel. Однако возникает серьезная проблема:методCurrentNumberявляется статическим, т.к. он должен работать со статическим объектомCurrentNumberChanged(). Как тогда получить доступ к объектуDependencyPropertyдля текущего экземпляраLabel? Нужная ссылка содержится в первом параметреShowNumberControl. Новое значение можно найти с применением входных аргументов события. Ниже показан необходимый код, который будет изменять свойствоDependencyObjectобъектаContent:Labelprivate static void CurrentNumberChanged(DependencyObject depObj,DependencyPropertyChangedEventArgs args){<b> // Привести DependencyObject к ShowNumberControl.</b>ShowNumberControl c = (ShowNumberControl)depObj;<b> // Получить элемент управления Label в ShowNumberControl.</b>Label theLabel = c.numberDisplay;<b> // Установить для Label новое значение.</b>