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
fonte
2012-02-11 06:13:51
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
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