2012-02-03 9 views
8

Ho uno stile TextBox che formatta un numero se la casella è sfocata, ma lascia il numero non formattato mentre viene modificato.Posso modificare le proprietà di un'associazione in un DataTrigger, senza conoscere l'associazione stessa?

Questo è lo stile che desidero per più caselle di testo numeriche, ma contengono tutti collegamenti di testo diversi. L'unica differenza tra il normale setter di testo e il settaggio del testo attivato è che il trigger ha StringFormat=N2 nell'associazione.

C'è un modo per rendere questo stile generico, ad esempio solo cambiando la proprietà StringFormat dell'associazione nel DataTrigger?

<TextBox> 
    <TextBox.Style> 
     <Style TargetType="{x:Type TextBox}"> 
       <Setter Property="Text" Value="{Binding SomeValue, StringFormat=N2, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" /> 
      <Style.Triggers> 
       <Trigger Property="IsKeyboardFocusWithin" Value="True"> 
        <Setter Property="Text" Value="{Binding SomeValue, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" /> 
       </Trigger> 
      </Style.Triggers> 
     </Style> 
    </TextBox.Style> 
</TextBox> 
+0

Penso che non sia possibile modificare le proprietà di una rilegatura dopo che è stata applicata. Almeno quando provo a cambiare la proprietà StringFormat di un bind esistente, ottengo un InvalidOperationException che dice "Binding non può essere cambiato dopo che è stato usato." A me sembra che non ci sia modo di creare una nuova associazione ogni volta che cambia lo stato attivo . – Clemens

+0

Pensavo ancora a questo, e consideravo una sorta di soluzione di proprietà 'Data' allegata in cui il gestore di modifica delle proprietà avrebbe collegato i gestori di GotFocus/LostFocus, ecc. Preferirei avere un TextBox derivato con proprietà' Data' e 'StringFormat ', che imposterà la proprietà' Text' in base ai loro valori e allo stato attuale del focus. – Clemens

risposta

0

Mi chiedo se si potrebbe forse avere una proprietà associata sulle modifiche per mantenere il valore formattato (solo legato al valore reale di modifica con uno StringFormat applicata), quindi nel vostro fuori grilletto fuoco si potrebbe imposta il valore di modifica a questa proprietà.

Ciò comporterebbe un collegamento circolare anche se la modifica non ha messa a fuoco, non so come reagisce WPF in tali situazioni.

0

Purtroppo questo è (a mia conoscenza) non possibile. Una soluzione possibile sarebbe la creazione programmatica di uno stile al volo, che potrebbe essere incapsulato in un MarkupExtension che prende il percorso come parametro costruttore.

2

Is c'è un modo in cui posso rendere questo stile generico, come solo cambiando la proprietà StringFormat del bind nel DataTrigger?

Eredita Style e nuova XAML sarebbe diventato questo:

<TextBox> 
    <TextBox.Style> 
     <local:FlyingStyle Binding="{Binding ElementName=This, Path=SomeValue}" StringFormat="F2" /> 
    </TextBox.Style> 
</TextBox> 

Ecco la classe ...

public class FlyingStyle : Style 
{ 
    public FlyingStyle() 
     : base(typeof(TextBox)) 
    { } 

    string _stringFormat; 
    public string StringFormat 
    { 
     get { return _stringFormat; } 
     set 
     { 
      _stringFormat = value; 
      CheckInitialize(); 
     } 
    } 
    Binding _binding; 
    public Binding Binding 
    { 
     get { return _binding; } 
     set 
     { 
      _binding = value; 
      CheckInitialize(); 
     } 
    } 
    void CheckInitialize() 
    { 
     if (StringFormat == null || Binding == null) { return; }// need both 

     Setters.Add(CreateSetter(Binding, StringFormat)); 

     var trigger = new Trigger 
     { 
      Property = UIElement.IsKeyboardFocusWithinProperty, 
      Value = true, 
     }; 
     trigger.Setters.Add(CreateSetter(Binding)); 
     Triggers.Add(trigger); 
    } 

    /// <summary>Creates the common <see cref="Setter"/>.</summary> 
    static Setter CreateSetter(Binding binding, string stringFormat = null) 
    { 
     // must create a copy, because same binding ref but diff StringFormats 
     var bindingCopy = new Binding 
     { 
      // these could be copies as well 
      UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged, 
      ValidatesOnDataErrors = true, 
      Mode = BindingMode.TwoWay, 
      Path = binding.Path, 

      AsyncState = binding.AsyncState, 
      BindingGroupName = binding.BindingGroupName, 
      BindsDirectlyToSource = binding.BindsDirectlyToSource, 
      Converter = binding.Converter, 
      ConverterCulture = binding.ConverterCulture, 
      ConverterParameter = binding.ConverterParameter, 
      ElementName = binding.ElementName, 
      FallbackValue = binding.FallbackValue, 
      IsAsync = binding.IsAsync, 
      NotifyOnSourceUpdated = binding.NotifyOnSourceUpdated, 
      NotifyOnTargetUpdated = binding.NotifyOnTargetUpdated, 
      NotifyOnValidationError = binding.NotifyOnValidationError, 
      //StringFormat = set below... 
      TargetNullValue = binding.TargetNullValue, 
      UpdateSourceExceptionFilter = binding.UpdateSourceExceptionFilter, 
      ValidatesOnExceptions = binding.ValidatesOnExceptions, 
      XPath = binding.XPath, 
      //ValidationRules = binding.ValidationRules 
     }; 
     // mutex ElementName, so modify if needed 
     // Source = binding.Source, 
     // RelativeSource = binding.RelativeSource, 

     if (stringFormat != null) 
     { 
      bindingCopy.StringFormat = stringFormat; 
     } 
     return new Setter(TextBox.TextProperty, bindingCopy); 
    } 
} 

Nota che il mio test è stato

  • MainWindow generica
  • impl INotifyPropertyChanged
  • SomeValue INPC proprietà
  • DataContext = questo
  • x: Name = Questo
+0

Preferirei lasciare il mio stile in XAML, dove posso facilmente accedervi per modificarlo. Questo sembra un incubo da mantenere :) – Rachel

+0

'Questo è lo stile che desidero per più caselle di testo numeriche, ma contengono tutti collegamenti di testo diversi ', fatto sembrare che valga il C#. In ogni caso il link nella risposta di David propone quasi lo stesso algoritmo. –

+0

+1 per una versione funzionante, anche se preferisco la Proprietà associata mostrata nel collegamento di David in quanto mi consente di mantenere il resto del mio stile in XAML – Rachel

2

Il mio tentativo di risolvere questo si è conclusa con un controllo personalizzato e un multi-vincolante, di cui tutt'e due dove suggerito sopra.

Questo mi ha permesso di usare marcatura in questo modo:

< CustomTextBox Value = "{Binding valore"} Format = "N2" />

ho cercato di inserire il mio codice, ma continuo a ricevere un errore su "codice che non è formattato correttamente come codice".

Problemi correlati