简体   繁体   English

WPF MVVM 依赖属性绑定不起作用

[英]WPF MVVM Dependancy property binding not working

I'm using a beavior in a TextBox control to filter input via a regex.我在 TextBox 控件中使用行为来通过正则表达式过滤输入。 For this I added a dependency property to get the regex value.为此,我添加了一个依赖属性来获取正则表达式值。 When I set directly in xaml the value, It works properly but when I'm trying to pass it with a bind property, the regex value is not setted in the dependency property:当我直接在 xaml 中设置该值时,它可以正常工作,但是当我尝试使用绑定属性传递它时,未在依赖属性中设置正则表达式值:

public class TextBoxInputRegExBehaviour : Behavior<TextBox>
{
    public static readonly DependencyProperty RegularExpressionProperty =
        DependencyProperty.Register("RegularExpression", typeof(string), typeof(TextBoxInputRegExBehaviour), new FrameworkPropertyMetadata(".*"));

    public string RegularExpression
    {
        get { return (string)GetValue(RegularExpressionProperty); 
        set { SetValue(RegularExpressionProperty, value); }
    }

    ... 
}

When using this format, no problem:使用这种格式时,没问题:

<TextBox Text="{Binding MyProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" Style="{StaticResource ValidableTextBox}">
     <i:Interaction.Behaviors>
         <behaviours:TextBoxInputRegExBehaviour RegularExpression="[0-9.]+$" />
     </i:Interaction.Behaviors>
 </TextBox>

But not working with binding:但不适用于绑定:

<TextBox Text="{Binding MyProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" Style="{StaticResource ValidableTextBox}">
     <i:Interaction.Behaviors>
         <behaviours:TextBoxInputRegExBehaviour RegularExpression="{Binding MyRegExString}" />
     </i:Interaction.Behaviors>
 </TextBox>

What did I wrong?我做错了什么?

Try to register RegularExpressionProperty to bind two-way by default:尝试注册RegularExpressionProperty ,默认绑定双向:

public static readonly DependencyProperty RegularExpressionProperty =
        DependencyProperty.Register("RegularExpression", 
        typeof(string), 
        typeof(TextBoxInputRegExBehaviour), 
        new FrameworkPropertyMetadata(".*", FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

Since Behavior<T> does not extend FrameworkElement , it does not have a DataContext .由于Behavior<T>没有扩展FrameworkElement ,因此它没有DataContext You can either use Binding.RelativeSource to traverse the visual tree to find the next parent FrameworkElement (and its DataContext property).您可以使用Binding.RelativeSource遍历可视化树以查找下一个父FrameworkElement (及其DataContext属性)。

Or implement an attached bahavior (based on attached properties).或者实现附加的行为(基于附加的属性)。
Since attached properties are usually attached to a FrameworkElement , you can always bind to the attaching element's DataContext (which is what you would naturally do).由于附加属性通常附加到FrameworkElement ,因此您始终可以绑定到附加元素的DataContext (这是您自然会做的)。
You can enforce a type constraint by checking the attaching element's type in the callback and throw an exception if necessary.您可以通过在回调中检查附加元素的类型来强制执行类型约束,并在必要时抛出异常。

Attached behavior usage example附加行为使用示例

<TextBox TextBoxInputRegExBehaviour.IsEnabled="True" 
         TextBoxInputRegExBehaviour.RegularExpression="{Binding MyRegExString}"
         Text="{Binding MyProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" 
         Style="{StaticResource ValidableTextBox}" />

TextBoxInputRegExBehaviour.cs TextBoxInputRegExBehaviour.cs
Implementation of an attached behavior附加行为的实现

public class TextBoxInputRegExBehaviour : DependencyObject
{
    public static readonly DependencyProperty IsEnabledProperty =
        DependencyProperty.RegisterAttached(
        "IsEnabled", 
        typeof(bool), 
        typeof(TextBoxInputRegExBehaviour), 
        new FrameworkPropertyMetadata(default(bool), OnIsEnabledChanged));
    
    public static void SetIsEnabled(DependencyObject attachingElement, bool value)
        => attachingElement.SetValue(IsEnabledProperty, value);
    public static bool GetIsEnabled(DependencyObject attachingElement)   
        => (bool)attachingElement.GetValue(IsEnabledProperty);

    public static readonly DependencyProperty RegularExpressionProperty =
        DependencyProperty.RegisterAttached(
        "RegularExpression", 
        typeof(string), 
        typeof(TextBoxInputRegExBehaviour), 
        new FrameworkPropertyMetadata(".*", OnRegularExpressionChanged));
    
    public static void SetRegularExpression(DependencyObject attachingElement, string value)
        => attachingElement.SetValue(RegularExpressionProperty, value);
    public static string GetRegularExpression(DependencyObject attachingElement)   
        => (string)attachingElement.GetValue(RegularExpressionProperty);

    private static void OnIsEnabledChanged(DependencyObject attachingElement, DependencyPropertyChangedEventArgs e) 
    {
        // Prior to C# 9: if (!(attachingElement is TextBox textBox))
        if (attachingElement is not TextBox textBox)
        {
            // Optionally throw an exception if this makes sense
            return;
        }

        if ((bool)e.NewValue)
        {
            // TODO::Handle behavior enabled, 
            // for example subscribe to events of the TextBox instance
        }
        else
        {
            // TODO::Handle behavior disabled, 
            // for example unsubscribe from events of the TextBox instance
        }
    }

    private static void OnRegularExpressionChanged(DependencyObject attachingElement, DependencyPropertyChangedEventArgs e) 
    {
        // Prior to C# 9: if (!(attachingElement is TextBox textBox))
        if (attachingElement is not TextBox textBox)
        {
            // Optionally throw an exception if this makes sense
            return;
        }


        // TODO::Handle the changed RegularExpression value
    }


    ... 
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM