2011-12-17 3 views
0

自分のフォームで自分のラベルスタイルを動的に変更しようとしています。 私がしたい振る舞いは:例えば、「txtName」というテキストボックスがFocusedになるたびに、「lblName」という名前のLabel Controlを検索し、FontWeightプロパティを「Bold」に変更する必要があります。一部のコントロールのトリガで、「ダイナミック」名前の別のコントロールのプロパティを変更する

'txtBirthday'という名前のテキストボックスと 'lblBirthday'というラベルの場合は同じです。ここで、 'txt'はTextBox、Labelはlblです。

すべてのテキストボックスには、対応するラベルのNAMEと接頭辞「txt」と接頭辞「lbl」がありますが、テキストボックスで対応するラベルが見つからない場合は何もしないでください。

つまり、テキストボックスがフォームに集中するたびに、説明のために「responsable」というラベルを検索し、フォントの太さを太字に変更してフォームをユーザーフレンドリーにする必要があります。そうすれば、ユーザーは入力したテキストボックスを混乱させることはありません。

私は多分良いスタートポイントであるとは言い難いコードですが、非静的なコントロール名を扱う方法はわかりません。上記のコメントで述べたよう

<Style TargetType="{x:Type Label}"> 

    <Style.Triggers> 
     <!-- Here is how we bind to another control's property --> 
     <DataTrigger Binding="{Binding IsFocused, ElementName=txtUser}" Value="True"> 
      <Setter Property="FontWeight" Value="Bold" /> 
      <!-- Here is the 'override' content --> 
     </DataTrigger> 

    </Style.Triggers> 

</Style> 
+0

XAMLで変数を使用できるようにはならないと思います。 gotfocusとフォーカスを失ったイベントハンドラを配置します。 – Paparazzi

+0

あなたの例はより複雑な設定の簡素化ですか?行動を変えるために名前を一致させることはお勧めできません。このアプローチは脆弱で、拡大縮小しません。これらは、より強固な他の組み込みの代替(コントロールテンプレート、ユーザーコントロールなど)です。 –

+0

@BalamBalam、いくつかのコントロールがあります。私はこれを行う巨大な仕事を持っています。それらをグローバルに定義する方法はありますか? –

答えて

0

は、探し、パターンが視覚的挙動を適用するための基礎として要素名を一致させる手法はロバストではありません。たとえば、タイプミスをして "lbl"の代わりに "lbel"を使用するとどうなりますか?または、後ですべてLabelsTextBlocksに置き換えることにした場合はどうなりますか?動作を維持するために、名前に接頭辞「lbl」を付けることはできますか?ビジュアルを変更するためのコードを使用することのもう一つの欠点は、プロパティがシーンの裏で変更されているので、XAMLだけを読むことからUIの動作を理解することがはるかに難しくなります。 WPFには、このアプローチよりも優先されるべき多くの方法が組み込まれています。

C#:あなたは代替実装に興味がある場合このアプローチを使用する必要がある場合は、ちょうど、私たちは言われていること:)

を助けるためにここにいる尋ね、ここにあなたの添付の行動は次のようになります。

public static class FontWeightFocusedHelper 
{ 
    private static readonly List<Label> Labels = new List<Label>(); 

    public static void SetChangeFontWeightOnTextBoxFocused(Label label, bool value) 
    { 
     label.SetValue(ChangeFontWeightOnTextBoxFocusedProperty, value); 
    } 

    public static bool GetChangeFontWeightOnTextBoxFocused(Label label) 
    { 
     return (bool) label.GetValue(ChangeFontWeightOnTextBoxFocusedProperty); 
    } 

    public static readonly DependencyProperty ChangeFontWeightOnTextBoxFocusedProperty = 
     DependencyProperty.RegisterAttached("ChangeFontWeightOnTextBoxFocused", typeof (bool), 
              typeof (FontWeightFocusedHelper), 
              new FrameworkPropertyMetadata(OnChangeFontWeightOnTextBoxFocusedPropertyChanged)); 

    private static void OnChangeFontWeightOnTextBoxFocusedPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     if (d is TextBox) 
     { 
      var textBox = (TextBox) d; 
      // Make sure to use a WeakEventManager here otherwise you will leak ... 
      textBox.GotFocus += OnTextBoxGotFocusChanged; 
      textBox.LostFocus += OnTextBoxLostFocusChanged; 
      return; 
     } 

     if (d is Label) 
     { 
      // Make sure to store WeakReferences here otherwise you will leak ... 
      Labels.Add((Label)d); 
      return; 
     } 

     throw new InvalidOperationException("ChangeFontWeightOnTextBoxFocused can only be set on TextBox and Label types."); 
    } 

    private static void OnTextBoxLostFocusChanged(object sender, RoutedEventArgs e) 
    { 
     SetMatchingLabelFontWeight(sender as TextBox, FontWeights.Regular); 
    } 

    private static void OnTextBoxGotFocusChanged(object sender, RoutedEventArgs e) 
    { 
     SetMatchingLabelFontWeight(sender as TextBox, FontWeights.Bold); 
    } 

    private static void SetMatchingLabelFontWeight(TextBox textBox, FontWeight fontWeight) 
    { 
     if (textBox != null) 
     { 
      // Suggest adding a property for LabelPrefix and TextBoxPrefix too, use them here 
      var label = Labels.Where(l => !String.IsNullOrEmpty(l.Name)) 
           .Where(l => l.Name.Replace("lbl", "txt") == textBox.Name) 
           .FirstOrDefault(); 

      if (label != null) 
      { 
       label.FontWeight = fontWeight; 
      } 
     } 
    } 
} 

XAML

<StackPanel > 
     <StackPanel.Resources> 
      <Style TargetType="{x:Type TextBox}"> 
       <Setter Property="l:FontWeightFocusedHelper.ChangeFontWeightOnTextBoxFocused" Value="True" /> 
      </Style> 
      <Style TargetType="{x:Type Label}"> 
       <Setter Property="l:FontWeightFocusedHelper.ChangeFontWeightOnTextBoxFocused" Value="True" /> 
      </Style> 
     </StackPanel.Resources> 
     <StackPanel Orientation="Horizontal">     
      <Label x:Name="lblOne" VerticalAlignment="Center" Content="First Name"/> 
      <TextBox x:Name="txtOne" Width="300" VerticalAlignment="Center"/> 
     </StackPanel> 
     <StackPanel Orientation="Horizontal"> 
      <Label x:Name="lblTwo" VerticalAlignment="Center" Content="Last Name" /> 
      <TextBox x:Name="txtTwo" Width="300" VerticalAlignment="Center" /> 
     </StackPanel> 
    </StackPanel> 

これは役に立ちます。

+0

ありがとうございます!それは魔法のように働いた! :) まさに私が欲しかったことです。 私はここでそれを尋ねることができない場合(または別の質問を開く必要がある場合)、それに対して良いアプローチは何でしょうか?私はその特定の効果について話しているわけではありませんが、ユーザーがテキストボックスを使ってフォーム内のどこにいるかを知るのに役立つ良い方法はありますか? –

+0

私は 'UserControl'やカスタム' Control'を使ってこのエフェクトを作成する方法について別の質問をすることをお勧めします。上記の例はちょうどです - それは確かに(固定されていない限り)メモリをリークし、正直なところ、 "動的な"名前を使用しない方が簡単です(そしてより一般的です)。 –

0

すべてのgotfocusを同じイベントにすることができます。送信者がイベントに渡されるので、送信者の名前を取得できます。コードビハインドでは、XAMLでは使用できない変数とロジックを使用できます。

+0

それは実際にはアプローチですが、私はよりグローバルなものを求めていました。ありがとうございました! –