2009-09-03 110 views
1

好吧 - 我把頭髮拉出我認爲是一個簡單的場景:爲包含兩個附加屬性(EnglishText,FrenchText)的雙語使用創建自定義標籤。目前,它的結構是這樣的:WPF自定義控件並通過DependencyProperty公開屬性

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」註冊。

我現在明白了,如果我將依賴屬性聲明更改爲共享,那麼這個問題就會消失 - 但這會導致許多其他問題,如需要共享回調函數 - 因此無法更新內容(需要用類實例化)。 我真正想要的是在英文和法文標籤更改時,設計時更新的內容屬性。

有沒有辦法解決這個問題?或者,也許是依賴屬性矯枉過正我需要什麼?

回答

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#語法)

+0

謝謝itowlson!依賴對象「d」整個時間都在注視着我,我從來沒有把兩個和兩個放在一起。 – Gatmando 2009-09-03 22:58:02

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 
+0

謝謝馬特 - 同樣的答案如下(我把它設置爲答案,因爲完整的)但是你的也是對的。我很感激幫助。 – Gatmando 2009-09-03 23:00:33

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 
相關問題