我可以在不知道绑定本身的情况下更改DataTrigger中绑定的属性吗?

时间:2012-02-03 13:09:16

标签: wpf xaml data-binding styles

我有TextBox样式,如果框未聚焦,则会格式化数字,但在编辑时会保留未格式化的数字。

这是我想要多个TextBoxes的样式,但它们都包含不同的Text绑定。常规文本设置器和触发文本设置器之间的唯一区别是触发器在绑定中具有StringFormat=N2

有没有办法让这个样式变得通用,例如只更改DataTrigger中绑定的StringFormat属性?

<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>

5 个答案:

答案 0 :(得分:2)

我看到的唯一选择是为StringFormat创建一个附加属性并使用multiBinding。

不是你想要的,但我认为足够接近......

您在S.O。上有更多关于此(重复的)问题的信息:

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

答案 1 :(得分:2)

  

有没有办法让这种风格变得通用,比如只改变   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);
    }
}

请注意,我的测试是

  • 通用MainWindow
  • impl INotifyPropertyChanged
  • SomeValue INPC属性
  • DataContext = this
  • x:名称=此

答案 2 :(得分:2)

我尝试解决这个问题最终得到了一个自定义控件和一个多重绑定,两者都在上面建议。

这允许我使用这样的标记:

&LT; CustomTextBox Value =“{Binding Value”} Format =“N2”/&gt;

我试图发布我的代码,但是我一直收到有关“代码格式不正确的代码”的错误。

答案 3 :(得分:0)

我想知道你是否可以在编辑中有一个附加属性来保存格式化的值(刚刚应用了Stringformat绑定到真正的编辑值),然后在你的焦点外触发器中你可以设置编辑值这个属性。

这会导致循环绑定,但编辑没有焦点时,不知道WPF在这种情况下如何反应。

答案 4 :(得分:0)

可悲的是,据我所知,这是不可能的。一种可能的解决方法是以编程方式动态创建这样的样式,可以封装在MarkupExtension中,该路径将路径作为构造函数参数。