0

我正在开发 WPF 表单设计器,您可以在其中将标签、文本框、组合框等控件拖放到设计图面上,然后通过属性网格用户可以为每个控件设置数据绑定。我需要为那些没有为给定属性设置绑定的控件显示红色背景。

我最初的想法是创建一个 HasBindingConverter,它将获取调用元素本身并检查它是否具有与某个属性的绑定。在这种情况下TextBox.TextProperty

public class HasBindingConverter: IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        FrameworkElement fe = value as FrameworkElement;
        if(fe != null)
        {
            Binding binding = BindingOperations.GetBinding(fe, TextBox.TextProperty);
            return binding != null;
        }
        return false;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return null;
    }
}

然后我将一个与 TextBox 控件类型关联的样式添加到我的表单的资源部分,它是一个用户控件:

<UserControl.Resources>
    <Style TargetType="TextBox">
        <Style.Resources>
            <Converters:HasBindingConverter x:Key="HasBindingConv"/>
        </Style.Resources>
        <Style.Triggers>
            <DataTrigger
            Binding="{Binding,
            RelativeSource={RelativeSource Self},
            Converter={StaticResource HasBindingConv}}"
            Value="False">
                <Setter Property="TextBox.Background" Value="Red" />
                </DataTrigger>
 <DataTrigger Binding="{Binding 
            RelativeSource={RelativeSource Self},
            Converter={StaticResource HasBindingConv}}"
            Value="True">
                <Setter Property="TextBox.Background" Value="White" />
        </Style.Triggers>
    </Style>

因此,如果 TextBox 没有为 TextBox.TextProperty 设置数据绑定,那么它将其背景设置为红色。这部分工作正常,问题是当用户为此控件设置 TextBox.TextProperty 绑定时,我的 Converter 不再被调用,因此背景保持红色。

任何人都知道在设置此控件的绑定后如何调用触发器?或任何其他建议,我可能以错误的方式处理问题。

谢谢!

4

2 回答 2

1

发生这种情况的原因是Binding不会再次作为源调用,即它TextBox本身一旦创建就永远不会改变!

假设您专注于TextBox.

  1. 因此,将 Container ( Window/ UserControl) 的 Tag 属性设置为当前控件。

    myWindow.Tag = FocusManager.GetFocusedElement(myWindow);
    
  2. 用这个改变触发器Binding

    <DataTrigger
        Binding="{Binding,
        Path=Tag,
        RelativeSource={RelativeSource AncestorType=Window},
        Converter={StaticResource HasBindingConv}}" .. >
    
  3. 刷新Tag的属性Window

    myWindow.Tag = null;
    myWindow.Tag = FocusManager.GetFocusedElement(myWindow);
    
于 2012-10-25T14:19:52.720 回答
0

我找到了另一种方法来解决这个问题。

我创建了一个 ControlHasBindingBehavior Attached 属性,最初将其设置为 false。

public class ControlHasBindingBehavior
{
    #region DependencyProperty HasBinding

    /// <summary>
    /// Registers a dependency property as backing store for the HasBinding property
    /// Very important to set default value to 'false'
    /// </summary>
    public static readonly DependencyProperty HasBindingProperty =
        DependencyProperty.RegisterAttached("HasBinding", typeof(bool), typeof(ControlHasBindingBehavior),
        new FrameworkPropertyMetadata(false,FrameworkPropertyMetadataOptions.AffectsRender));

    /// <summary>
    /// Gets or sets the HasBinding.
    /// </summary>
    /// <value>The HasBinding.</value>
    public static bool GetHasBinding(DependencyObject d)
    {
        return (bool)d.GetValue(HasBindingProperty);
    }

    public static void SetHasBinding(DependencyObject d, bool value)
    {
        d.SetValue(HasBindingProperty, value);
    }

    #endregion
}

然后在我的 FormDesigner 视图中,我为所有 TextBoxes 创建了一个样式和触发器,因此当 Textbox 'HasBinding' 附加属性为 false 时,它​​会将背景变为红色:

        <Style TargetType="TextBox">
        <Style.Triggers>
            <Trigger Property="Behaviors:ControlHasBindingBehavior.HasBinding" Value="False">
                <Setter Property="Background" Value="Red"/>
            </Trigger>
        </Style.Triggers>
    </Style>

最后,当用户为给定控件成功设置绑定时,我将附加属性设置为“真”:

                ControlHasBindingBehavior.SetHasBinding(SelectedObject,true);

发生这种情况时,我的 TextBox.Background 再次变为白色 :) 最初我想以通用方式将样式触发器应用于所有 UIElements、FrameworkElements 或控件,但根据这个线程似乎这是不可能的

希望有人觉得它有用

于 2012-11-02T13:13:59.143 回答