그것은 연결된 속성으로 가능이지만, 당신이 완전히 바인딩을 교체해야 의미, 다음을 다시 넣어.
public static class TextBoxBehavior
{
#region StringFormat
public static string GetStringFormat(TextBox obj)
{
return (string)obj.GetValue(StringFormatProperty);
}
public static void SetStringFormat(TextBox obj, string value)
{
obj.SetValue(StringFormatProperty, value);
}
public static readonly DependencyProperty StringFormatProperty =
DependencyProperty.RegisterAttached(
"StringFormat",
typeof(string),
typeof(TextBoxBehavior),
new UIPropertyMetadata(
null,
StringFormatChanged));
// Used to store the original format
private static readonly DependencyPropertyKey OriginalBindingPropertyKey =
DependencyProperty.RegisterAttachedReadOnly(
"OriginalBinding",
typeof(BindingBase),
typeof(TextBoxBehavior),
new UIPropertyMetadata(null));
private static void StringFormatChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
TextBox textBox = o as TextBox;
if (textBox == null)
return;
string oldValue = (string)e.OldValue;
string newValue = (string)e.NewValue;
if (!string.IsNullOrEmpty(oldValue) && string.IsNullOrEmpty(newValue))
{
// Update target for current binding
UpdateTextBindingSource(textBox);
// Restore original binding
var originalBinding = (BindingBase)textBox.GetValue(OriginalBindingPropertyKey.DependencyProperty);
if (originalBinding != null)
BindingOperations.SetBinding(textBox, TextBox.TextProperty, originalBinding);
textBox.SetValue(OriginalBindingPropertyKey, null);
}
else if (!string.IsNullOrEmpty(newValue) && string.IsNullOrEmpty(oldValue))
{
// Get current binding
var originalBinding = BindingOperations.GetBinding(textBox, TextBox.TextProperty);
if (originalBinding != null)
{
// Update target for current binding
UpdateTextBindingSource(textBox);
// Create new binding
var newBinding = CloneBinding(originalBinding);
newBinding.StringFormat = newValue;
// Assign new binding
BindingOperations.SetBinding(textBox, TextBox.TextProperty, newBinding);
// Store original binding
textBox.SetValue(OriginalBindingPropertyKey, originalBinding);
}
}
}
private static void UpdateTextBindingSource(TextBox textBox)
{
var expr = textBox.GetBindingExpression(TextBox.TextProperty);
if (expr != null &&
expr.ParentBinding != null &&
(expr.ParentBinding.Mode == BindingMode.Default // Text binds two-way by default
|| expr.ParentBinding.Mode == BindingMode.TwoWay
|| expr.ParentBinding.Mode == BindingMode.OneWayToSource))
{
expr.UpdateSource();
}
}
private static Binding CloneBinding(Binding original)
{
var copy = new Binding
{
Path = original.Path,
XPath = original.XPath,
Mode = original.Mode,
Converter = original.Converter,
ConverterCulture = original.ConverterCulture,
ConverterParameter = original.ConverterParameter,
FallbackValue = original.FallbackValue,
TargetNullValue = original.TargetNullValue,
NotifyOnSourceUpdated = original.NotifyOnSourceUpdated,
NotifyOnTargetUpdated = original.NotifyOnTargetUpdated,
NotifyOnValidationError = original.NotifyOnValidationError,
UpdateSourceExceptionFilter = original.UpdateSourceExceptionFilter,
UpdateSourceTrigger = original.UpdateSourceTrigger,
ValidatesOnDataErrors = original.ValidatesOnDataErrors,
ValidatesOnExceptions = original.ValidatesOnExceptions,
BindingGroupName = original.BindingGroupName,
BindsDirectlyToSource = original.BindsDirectlyToSource,
AsyncState = original.AsyncState,
IsAsync = original.IsAsync,
StringFormat = original.StringFormat
};
if (original.Source != null)
copy.Source = original.Source;
if (original.RelativeSource != null)
copy.RelativeSource = original.RelativeSource;
if (original.ElementName != null)
copy.ElementName = original.ElementName;
foreach (var rule in original.ValidationRules)
{
copy.ValidationRules.Add(rule);
}
return copy;
}
#endregion
}
사용법 :
가 여기에 신속하고 더러운 구현의
<TextBox x:Name="ContractAmountTextBox"
Text="{Binding Path=ContractAmount, UpdateSourceTrigger=LostFocus, StringFormat=c}">
<TextBox.Style>
<Style TargetType="{x:Type TextBox}">
<Style.Triggers>
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter Property="local:TextBoxBehavior.StringFormat" Value="N"/>
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
이를 사용하여, 당신은 또한
감사 토마스, 그건 꽤 깔끔한 다른 텍스트 상자의 스타일을 다시 사용할 수 있습니다. 두 가지 질문이 있습니다. 스타일의 DataTrigger Binding에서 ElementName을 참조하십시오. 리소스 딕셔너리에서 스타일을 정의하고 여러 텍스트 상자에서 스타일을 다시 사용하려면 어떻게 일반화 할 수 있습니까? 두 번째는 바인딩을 수동으로 바꾸어서 예기치 않은 부작용이 생길 우려가 있다는 것입니다. Binding 모델이 향후 .NET 버전에서 확장되어 더 이상 모든 매개 변수를 복사하지 않을 수 있습니까? –
ElementName에 대해서는 실제로 코드를 복사했습니다.). ElementName은 필요 없으며 DataTrigger 대신 일반적인 Trigger를 사용할 수 있습니다. 내 대답을 업데이트 할게. –
네, .NET의 향후 버전에서는 작동하지 않을 수도 있습니다 ... –