присоединенное свойство уже зарегистрировано моим общим классом BaseAttachedProperty вызывает исключение времени разработки - PullRequest
0 голосов
/ 24 мая 2019

Я разрабатываю инженерное приложение для работы в WPF с VB.net и имею базовый класс для прикрепленных свойств, основанный на коде Angel Six *1002* в C #.Мое базовое вложенное свойство работает нормально во время выполнения, так как приложение выполняется без проблем, но по какой-то причине время разработки Visual Studio 2017 неожиданно начало генерировать исключения для всех моих вложенных свойств, что приводит к ошибке, свойство «Значение» уже зарегистрировано«BaseAttachedProperty'2_1_190297300».Это усложняет разработку любого дальнейшего пользовательского интерфейса.

Мои проблемы начались, когда я представил объект зависимости в пользовательском элементе управления, который вызывал событие обновления при каждом его обновлении, а затем вручную обновлял контекст данных пользовательского элемента управления.контроль.Это позволило пользовательскому элементу управления обновить главную страницу, на которой он был создан.

С тех пор я удалил пользовательский элемент управления и объект зависимости, но проблема все еще остается.Затем я закрыл свое решение, закрыл Visual Studio, удалил папки bin и obj и перезапустил, но проблема сохраняется.

В последние несколько дней я много раз искал в Интернете и переполнял стек, но покаЯ не смог найти решение, что необычно, потому что до сих пор я всегда мог решить любые проблемы, которые у меня были, с помощью поиска в Google.Хотя ошибка «свойство уже зарегистрировано», по-видимому, является обычной, решение проблем, связанных с этой ошибкой, во всех случаях кажется другим.

Это мое базовое присоединенное свойство со стандартным get/ код удаленного значения вместе с переопределяемыми методами событий ...

Public MustInherit Class BaseAttachedProperty(Of Parent As {BaseAttachedProperty(Of Parent, [Property]), New}, [Property])

    Private Shared defaultVal As [Property] = Nothing

#Region "Public Events"


#End Region

#Region "Public Properties"

    Public Shared Property Instance As Parent = New Parent()

#End Region

#Region "Attached Property Definitions"

    Public Shared ReadOnly ValueProperty As DependencyProperty = DependencyProperty.RegisterAttached(
        "Value",
        GetType([Property]),
        GetType(BaseAttachedProperty(Of Parent, [Property])),
        New UIPropertyMetadata(defaultVal,
                               New PropertyChangedCallback(AddressOf OnValuePropertyChanged),
                               New CoerceValueCallback(AddressOf OnValuePropertyUpdated)))


    Private Shared Sub OnValuePropertyChanged(d As DependencyObject, e As DependencyPropertyChangedEventArgs)

        TryCast(Instance, BaseAttachedProperty(Of Parent, [Property]))?.OnValueChanged(d, e)

        TryCast(Instance, BaseAttachedProperty(Of Parent, [Property]))?.ValueChanged(d, e)

    End Sub

    Private Shared Function OnValuePropertyUpdated(d As DependencyObject, value As Object) As Object

        TryCast(Instance, BaseAttachedProperty(Of Parent, [Property]))?.OnValueUpdated(d, value)

        TryCast(Instance, BaseAttachedProperty(Of Parent, [Property]))?.ValueUpdated(d, value)

        Return value

    End Function

Код присоединенного свойства, которое затем передает не более чем статическое значение, выглядит следующим образом ...

Public Class ControlTitleProperty
    Inherits BaseAttachedProperty(Of ControlTitleProperty, String)

End Class

Присоединенные свойства затем вызываются в xaml, как и следовало ожидать ...

<TextBox Text="{Binding PhasePageViewModel.ViscosityValue, 
                                                    Source={x:Static local:ViewModelLocator.Instance},
                                                    UpdateSourceTrigger=PropertyChanged,
                                                    ValidatesOnDataErrors=True,
                                                    Mode=TwoWay}"
                                     Style="{StaticResource ValueAndUnitsBox}"
                                     local:NumericInputProperty.Value="True"
                                     local:ControlTitleProperty.Value="Viscosity"
                                     local:ControlDescriptionProperty.Value="The viscosity of this phase and the associated units"/>

Поскольку я использую вложенные свойства в большинстве своих словарей ресурсов, время разработки не 'не работает должным образом где-нибудь в моем проекте, поэтому я очень признателен за помощь в его исправлении.Последние несколько дней я чесал голову, но безрезультатно.

Ответы [ 2 ]

0 голосов
/ 30 мая 2019

После долгих размышлений и помощи Фила, чтобы убедиться, что мой базовый класс свойств был максимально приближен к исходному коду C #, я постепенно перестроил свой пользовательский интерфейс в новый проект по частям,начиная с прикрепленных свойств.После добавления каждого класса в новый проект в качестве существующего элемента из старого проекта я бы очистил и собрал проект, чтобы посмотреть, не нарушит ли это конструктор Visual Studio.К моему удивлению, ни один из моих кодов не смог сломать конструктор, и в итоге я получил точную копию моего старого проекта, но теперь, когда дизайнер в Visual Studio снова работает.

Я могу только догадываться, что когдаЯ ввел свое собственное свойство зависимостей для контекста данных своего пользовательского элемента управления, и мне удалось сломать конструктор так, что его нельзя было отменить, просто удалив нарушающий код и затем перестроив. В этом блоге Трэвиса Иллига упоминается «теневой кэш», который используется дизайнером для визуализации внешнего вида вашего пользовательского интерфейса во время разработки в Visual Studio.Я считаю, что это то, что мне удалось сломать.

Мне потребовалось несколько кропотливых дней, чтобы перестроить мой проект, дни, которые я мог бы сэкономить, если бы у меня была недавняя резервная копия моего проекта.Так что на случай, если в будущем эта проблема снова возникнет, я собираюсь регулярно поддерживать свой проект!

0 голосов
/ 25 мая 2019

Я предполагаю, что ваш класс основан на классе C #, похожем на приведенный здесь:

https://www.csharpcodi.com/vs2/306/fasetto-word/Source/Fasetto.Word/AttachedProperties/BaseAttachedProperty.cs/#

В вашем коде две функции OnValuePropertyChanged и OnValuePropertyUpdated вызывают методValueUpdated.

Private Shared Sub OnValuePropertyChanged(d As DependencyObject, e As DependencyPropertyChangedEventArgs)
    TryCast(Instance, BaseAttachedProperty(Of Parent, [Property]))?.OnValueChanged(d, e)
    TryCast(Instance, BaseAttachedProperty(Of Parent, [Property]))?.ValueChanged(d, e)
End Sub

Private Shared Function OnValuePropertyUpdated(d As DependencyObject, value As Object) As Object
    TryCast(Instance, BaseAttachedProperty(Of Parent, [Property]))?.OnValueUpdated(d, value)
    TryCast(Instance, BaseAttachedProperty(Of Parent, [Property]))?.ValueUpdated(d, value)
    Return value
End Function

Если я прав насчет исходного кода C #, то ValueUpdated на самом деле является событием, а не методом.

В VB.NET вы не можете вызвать событие с этим синтаксисом, выЯ должен использовать оператор RaiseEvent.

Я не думаю, что есть прямой способ вызвать событие из статического метода в VB.NET.Я бы порекомендовал определить нестатический член и вызвать его через указатель экземпляра.

Private Shared Sub OnValuePropertyChanged(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
    TryCast(Instance, BaseAttachedProperty(Of Parent, [Property]))?.OnValueChanged(d, e)
    TryCast(Instance, BaseAttachedProperty(Of Parent, [Property]))?.FireValueChanged(d, e)
End Sub

Private Sub FireValueChanged ( d As DependencyObject, value As DependencyPropertyChangedEventArgs )
  RaiseEvent ValueUpdated ( d, value )
End Sub

В качестве альтернативы вы можете вызвать событие из метода OnValueChanged.

Это полный класс, который я сгенерировал путем автоматического преобразования кода C #, а затем исправил ошибки компиляции.

Imports System
Imports System.ComponentModel
Imports System.Windows

Public MustInherit Class BaseAttachedProperty(Of Parent As New, [Property])

    Public Event ValueChanged As Action(Of DependencyObject, DependencyPropertyChangedEventArgs)
    Public Event ValueUpdated As Action(Of DependencyObject, Object)

    Public Shared Property Instance As Parent = New Parent()

    Private Shared defValue As [Property] = Nothing

    Public Shared ReadOnly ValueProperty As DependencyProperty _
                      = DependencyProperty.RegisterAttached ( "Value", _
                                                              GetType([Property]), _
                                                              GetType(BaseAttachedProperty(Of Parent, [Property])), _
                                                              New UIPropertyMetadata ( defValue, _
                                                                                       New PropertyChangedCallback(AddressOf OnValuePropertyChanged), _
                                                                                       New CoerceValueCallback(AddressOf OnValuePropertyUpdated)) )

    Public Property Value as [Property]

    Private Shared Sub OnValuePropertyChanged(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
        TryCast(Instance, BaseAttachedProperty(Of Parent, [Property]))?.OnValueChanged(d, e)
        TryCast(Instance, BaseAttachedProperty(Of Parent, [Property]))?.FireValueChanged(d, e)
    End Sub

    Private Shared Function OnValuePropertyUpdated(ByVal d As DependencyObject, ByVal value As Object) As Object
        TryCast(Instance, BaseAttachedProperty(Of Parent, [Property]))?.OnValueUpdated(d, value)
        TryCast(Instance, BaseAttachedProperty(Of Parent, [Property]))?.FireValueUpdated(d, value)
        Return value
    End Function

    Private Sub FireValueChanged ( d As DependencyObject, value As DependencyPropertyChangedEventArgs )
      RaiseEvent ValueChanged ( d, value )
    End Sub

    Private Sub FireValueUpdated ( d As DependencyObject, value As [Property] )
      RaiseEvent ValueUpdated ( d, value )
    End Sub

    Public Shared Function GetValue(ByVal d As DependencyObject) As [Property]
        Return CType(d.GetValue(ValueProperty), [Property])
    End Function

    Public Shared Sub SetValue(ByVal d As DependencyObject, ByVal value As [Property])
        d.SetValue(ValueProperty, value)
    End Sub

    Public Overridable Sub OnValueChanged(ByVal sender As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
    End Sub

    Public Overridable Sub OnValueUpdated(ByVal sender As DependencyObject, ByVal value As Object)
    End Sub
End Class

Я проверил этот код с использованием трех определений атрибутов

Public Class ControlDescriptionProperty
 Inherits BaseAttachedProperty(Of ControlDescriptionProperty, String)

End Class

Public Class ControlTitleProperty
 Inherits BaseAttachedProperty(Of ControlTitleProperty, String)

End Class

Public Class NumericInputProperty
 Inherits BaseAttachedProperty(Of NumericInputProperty, Boolean)

End Class

При использовании следующего кода XAML он не генерирует ошибку во время выполнения или в конструкторе:

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...