Can I change the properties of a binding in a DataTrigger, without knowing the binding itself?

后端 未结 5 1271
甜味超标
甜味超标 2021-01-04 13:50

I have a TextBox style that formats a number if the box is unfocused, but leaves the number unformatted whlie it\'s being edited.

This is the style I wa

相关标签:
5条回答
  • 2021-01-04 14:23

    Is there a way I can make this style generic, such as only changing the StringFormat property of the binding in the DataTrigger?

    Inherit Style and new XAML would become this:

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

    Here's the class...

    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);
        }
    }
    

    Note that my test was

    • the generic MainWindow
    • impl INotifyPropertyChanged
    • SomeValue INPC property
    • DataContext = this
    • x:Name = This
    0 讨论(0)
  • 2021-01-04 14:25

    My attempt to solve this ended up with a custom control plus a multi-binding, both of which where suggested above.

    This allowed me to use markup like this:

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

    I tried to post my code but I keep getting an error about "code that is not properly formatted as code".

    0 讨论(0)
  • 2021-01-04 14:31

    I'm wondering if you could maybe have an attached property on the edits to hold the formatted value (just bound to the real edit value with a Stringformat applied), then in your out of focus trigger you could set the edit value to this property.

    This would result in a circular binding though when the edit doesn't have focus, dunno how WPF reacts in such situations.

    0 讨论(0)
  • 2021-01-04 14:36

    The only option I see there would be to create an attached property for the StringFormat and use a multiBinding.

    Not quite what you wanted, but close enough, I guess...

    you have more info on this (kind of duplicate) question on S.O.:

    Modifying the Parameters of a TextBox's Text Binding through the use of a Style

    0 讨论(0)
  • 2021-01-04 14:41

    Sadly this is (to my knowledge) not possible. One possible workaround would be programmatically creating such a style on the fly, that could be encapsulated in a MarkupExtension which takes the path as constructor parameter.

    0 讨论(0)
提交回复
热议问题