好的 - 我正在把头发拉出我认为是一个简单的场景:为双语使用创建一个包含两个附加属性的自定义标签(EnglishText,FrenchText)。目前它的结构如下:
Public Class myCustomLabel
Inherits System.Windows.Controls.Label
Public myEnglishTextProperty As DependencyProperty = DependencyProperty.Register("myEnglishText", GetType(String), GetType(myCustomLabel), New PropertyMetadata("English", New PropertyChangedCallback(AddressOf TextChanged)))
Public myFrenchTextProperty As DependencyProperty = DependencyProperty.Register("myFrenchText", GetType(String), GetType(myCustomLabel), New PropertyMetadata("Francais", New PropertyChangedCallback(AddressOf TextChanged)))
Public Sub New()
'This OverrideMetadata call tells the system that this element wants to provide a style that is different than its base class.
'This style is defined in themes\generic.xaml
DefaultStyleKeyProperty.OverrideMetadata(GetType(myCustomLabel), New FrameworkPropertyMetadata(GetType(myCustomLabel)))
End Sub
Public Property myEnglishText() As String
Get
Return MyBase.GetValue(myFrenchTextProperty)
End Get
Set(ByVal value As String)
MyBase.SetValue(myFrenchTextProperty, value)
End Set
End Property
Public Property myFrenchText() As String
Get
Return MyBase.GetValue(myFrenchTextProperty)
End Get
Set(ByVal value As String)
MyBase.SetValue(myFrenchTextProperty, value)
End Set
End Property
Private Sub TextChanged(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
If DesignerProperties.GetIsInDesignMode(Me) = True Then
Me.Content = myEnglishText
Else
If myUser.Language = "E" Then
Me.Content = myEnglishText
Else
Me.Content = myFrenchText
End If
End If
End Sub
End Class
我的测试窗口网格xaml很简单:
<Grid>
<my:myCustomLabel myEnglishText="English Text" myFrenchText="English Text" Height="25" Width="100" Background="Aqua" Foreground="Black"/>
</Grid>
这似乎适用于开发环境 - 更改英语和法语文本会更改设计预览,并且当应用程序运行并打开测试窗口时它会起作用。但只是第一次 - 如果我第二次打开测试窗口,我会收到以下消息:
'myEnglishText'属性已经存在 由'myCustomLabel'注册。
我现在明白,如果我将依赖属性声明更改为共享,那么这个问题就会消失 - 但这会导致许多其他问题,例如需要共享回调函数 - 因此无法更新内容(需要用类实例化)。 我真正想要的是在更改英文和法文标签时设计时更新的内容属性。
有解决方法吗?或者也许依赖属性过度杀伤我需要什么?
答案 0 :(得分:7)
您正在将依赖项属性注册为实例变量,并在实例构造函数中注册。因此,每次实例化控件时,它们都会再次注册,这会导致第二次出错。如您所知,依赖属性需要是静态(共享)成员:
Public Shared myEnglishTextProperty As DependencyProperty =
DependencyProperty.Register("myEnglishText", GetType(String), GetType(myCustomLabel),
New PropertyMetadata("English", New PropertyChangedCallback(AddressOf TextChanged)))
您可能需要在共享构造函数(类型初始化函数)中调用OverrideMetadata而不是实例构造函数。
关于需要共享回调的问题:是的,它会是,但回调的一个参数是标签实例。所以你可以将它转换为标签并在其上调用实例方法:
private static void TextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((MyLabel)d).TextChanged();
}
private void TextChanged()
{
// your code here
}
(原谅C#语法)
答案 1 :(得分:2)
您是否因为访问“我”实例而不希望共享回调方法?如果就是这样,请将其共享并使用“d”参数。我不太了解VB以显示代码,但只需创建一个myCustomLabel类型的变量并为其指定“d”(使用强制转换)。然后使用该变量(比如说“lbl”):
If DesignerProperties.GetIsInDesignMode(lbl) = True Then
lbl.Content = myEnglishText
Else
If myUser.Language = "E" Then
lbl.Content = myEnglishText
Else
lbl.Content = myFrenchText
End If
End If
答案 2 :(得分:1)
此外,您的示例代码中存在轻微错误。试试这个:
Public Property myEnglishText() As String
Get
Return MyBase.GetValue(myEnglishTextProperty)
End Get
Set(ByVal value As String)
MyBase.SetValue(myEnglishTextProperty, value)
End Set
End Property
而不是:
Public Property myEnglishText() As String
Get
Return MyBase.GetValue(myFrenchTextProperty)
End Get
Set(ByVal value As String)
MyBase.SetValue(myFrenchTextProperty, value)
End Set
End Property