是有一種方法可以使此風格具有通用性,例如僅更改DataTrigger中綁定的StringFormat屬性 ?
繼承Style
和新的XAML將成爲這樣的:
<TextBox>
<TextBox.Style>
<local:FlyingStyle Binding="{Binding ElementName=This, Path=SomeValue}" StringFormat="F2" />
</TextBox.Style>
</TextBox>
這裏的類...
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);
}
}
請注意,我的測試是
- 通用主窗口
- 個IMPL INotifyPropertyChanged的
SomeValue
INPC財產
- 的DataContext =這個
- X:名稱=這
我認爲不可能在應用後改變綁定的任何屬性。至少當我嘗試更改現有綁定的StringFormat屬性時,我得到一個InvalidOperationException,說'綁定在使用後無法更改'。對我來說,似乎沒有辦法在每次焦點更改時都創建一個新綁定。 – Clemens 2012-02-03 14:18:01
再次考慮了這個問題,並考慮了某種附加的'Data'屬性解決方案,其中屬性更改處理程序將附加GotFocus/LostFocus處理程序等。最後,我希望有一個派生的TextBox,其中包含屬性'Data'和'StringFormat ',它將根據它們的值和當前焦點狀態來設置「文本」屬性。 – Clemens 2012-02-04 08:53:51