2009-09-03 4 views
1

[OK] - 単純なシナリオであると思っていたものを私の頭の中に残しています:2つの追加プロパティ(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

あなたはインスタンス変数としてあなたの依存関係プロパティを登録し、インスタンスコンストラクタの間にされています。したがって、コントロールをインスタンス化するたびに再度登録されるため、2回目にエラーが発生します。あなたが判明したように、依存関係プロパティは、静的(共有)メンバーである必要があります。

Public Shared myEnglishTextProperty As DependencyProperty = 
    DependencyProperty.Register("myEnglishText", GetType(String), GetType(myCustomLabel), 
    New PropertyMetadata("English", New PropertyChangedCallback(AddressOf TextChanged))) 

あなたはおそらく同様に、むしろあなたのインスタンスコンストラクタよりも共有コンストラクタ(タイプ初期化子)にOverrideMetadataを呼び出す必要があります。

共有する必要があるコールバックに関する問題について:はい、そうですが、コールバックの引数の1つはラベルインスタンスです。だから、あなただけのラベルにし、その上のインスタンスメソッドを呼び出すことをキャストすることができます:

private static void TextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
{ 
    ((MyLabel)d).TextChanged(); 
} 

private void TextChanged() 
{ 
    // your code here 
} 

(C#構文を許す)

+0

ありがとうございますitowlson!依存関係のオブジェクト "d"は、全面的に私を見つめていました。私は決して2つと2つを入れませんでした。 – Gatmando

2

"me"インスタンスにアクセスしているためにコールバックメソッドを共有しないようにする理由はありますか?それがすべてであれば、それを共有して、 "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

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