2011-12-17 2 views
0

Я пытаюсь изменить стиль ярлыков динамически на своих формах. Поведение, которое я хочу: каждый раз, когда текстовое поле, называемое «txtName», например, получает Focused, оно должно искать элемент управления ярлыками с именем lblName и изменять его свойство FontWeight на «Bold».Изменение свойства другого элемента управления в триггере элемента управления с «динамическим» именем

То же самое для текстового поля под названием «txtBirthday» и ярлыка «lblBirthday», где «txt» обозначает TextBox и lbl для Label.

В каждом текстовом поле есть ИМЯ и префикс «txt» и префикс «lbl» для соответствующей метки, но если текстовое поле не находит метку соответствия, оно ничего не должно делать.

Другими словами, каждый раз, когда текстовое поле фокусируется на форме, оно должно искать метку «ответственно» для ее описания и замаскировать ее (изменяя ее размер шрифта до полужирного), чтобы форма была более удобной для пользователя. Таким образом, пользователь не запутается в текстовом поле, которое он вводит.

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

<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

Как указано в комментариях выше, метод поиска элементов и сопоставления имен элементов в качестве основы для применения визуального поведения не является надежным. Например, что происходит, когда вы делаете опечатку и используете «lbel» вместо «lbl»? Или что произойдет, если позже вы решите заменить все Labels на TextBlocks. Вы все еще комментируете свои имена префиксом «lbl», чтобы сохранить поведение? Еще один недостаток использования кода для изменения визуальных эффектов - теперь понимание поведения вашего пользовательского интерфейса от чтения XAML становится намного сложнее, поскольку свойства меняются за кулисами. 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

То есть подход, действительно, но я хотел что-то более глобальное. Спасибо! –

 Смежные вопросы

  • Нет связанных вопросов^_^