加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 没有setter的属性上的DataBinding

发布时间:2020-12-15 21:54:29 所属栏目:百科 来源:网络整理
导读:如何将数据绑定到只有getter的属性,而没有setter从wpf中的视图模型访问它?我正在使用PasswordBox并希望将其SecureString属性绑定到ViewModel属性.我怎样才能做到这一点? 解决方法 我使用这个类和 System.Windows.Interactivity库来访问没有setter的属性:
如何将数据绑定到只有getter的属性,而没有setter从wpf中的视图模型访问它?我正在使用PasswordBox并希望将其SecureString属性绑定到ViewModel属性.我怎样才能做到这一点?

解决方法

我使用这个类和 System.Windows.Interactivity库来访问没有setter的属性:

public sealed class PropertyManager : TriggerAction<FrameworkElement>
{
    #region Fields

    private bool _bindingUpdating;
    private PropertyInfo _currentProperty;
    private bool _propertyUpdating;

    #endregion

    #region Dependency properties

    /// <summary>
    ///     Identifies the <see cref="Binding" /> dependency property.
    /// </summary>
    public static readonly DependencyProperty BindingProperty =
        DependencyProperty.Register("Binding",typeof(object),typeof(PropertyManager),new PropertyMetadata((o,args) =>
            {
                var propertyManager = o as PropertyManager;
                if (propertyManager == null ||
                    args.OldValue == args.NewValue) return;
                propertyManager.TrySetProperty(args.NewValue);
            }));

    /// <summary>
    ///     Identifies the <see cref="SourceProperty" /> dependency property.
    /// </summary>
    public static readonly DependencyProperty SourcePropertyProperty =
        DependencyProperty.Register("SourceProperty",typeof(string),new PropertyMetadata(default(string)));

    /// <summary>
    ///     Binding for property <see cref="SourceProperty" />.
    /// </summary>
    public object Binding
    {
        get { return GetValue(BindingProperty); }
        set { SetValue(BindingProperty,value); }
    }

    /// <summary>
    ///     Name property to bind.
    /// </summary>
    public string SourceProperty
    {
        get { return (string)GetValue(SourcePropertyProperty); }
        set { SetValue(SourcePropertyProperty,value); }
    }

    #endregion

    #region Methods

    /// <summary>
    ///     Invokes the action.
    /// </summary>
    /// <param name="parameter">
    ///     The parameter to the action. If the action does not require a parameter,the parameter may be
    ///     set to a null reference.
    /// </param>
    protected override void Invoke(object parameter)
    {
        TrySetBinding();
    }

    /// <summary>
    ///     Tries to set binding value.
    /// </summary>
    private void TrySetBinding()
    {
        if (_propertyUpdating) return;
        PropertyInfo propertyInfo = GetPropertyInfo();
        if (propertyInfo == null) return;
        if (!propertyInfo.CanRead)
            return;
        _bindingUpdating = true;
        try
        {
            Binding = propertyInfo.GetValue(AssociatedObject,null);
        }
        finally
        {
            _bindingUpdating = false;
        }
    }

    /// <summary>
    ///     Tries to set property value.
    /// </summary>
    private void TrySetProperty(object value)
    {
        if (_bindingUpdating) return;
        PropertyInfo propertyInfo = GetPropertyInfo();
        if (propertyInfo == null) return;
        if (!propertyInfo.CanWrite)
            return;
        _propertyUpdating = true;
        try
        {
            propertyInfo.SetValue(AssociatedObject,value,null);
        }
        finally
        {
            _propertyUpdating = false;
        }
    }

    private PropertyInfo GetPropertyInfo()
    {
        if (_currentProperty != null && _currentProperty.Name == SourceProperty)
            return _currentProperty;
        if (AssociatedObject == null)
            throw new NullReferenceException("AssociatedObject is null.");
        if (string.IsNullOrEmpty(SourceProperty))
            throw new NullReferenceException("SourceProperty is null.");
        _currentProperty = AssociatedObject
            .GetType()
            .GetProperty(SourceProperty);
        if (_currentProperty == null)
            throw new NullReferenceException("Property not found in associated object,property name: " +
                                                SourceProperty);
        return _currentProperty;
    }

    #endregion
}

要在XAML中使用此类,您需要添加对System.Windows.Interactivity库的引用并添加此命名空间:

xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:behaviors="clr-namespace:YOUR NAMESPACE WHERE YOU PUT THE PropertyManager CLASS"

您还需要指定将更新的事件值,在本例中为PasswordChanged并指定要绑定的属性,在本例中为Password:

<PasswordBox>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="PasswordChanged">
            <behaviors:PropertyManager
                Binding="{Binding Path=MyPasswordProperty,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
                SourceProperty="Password" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
</PasswordBox>

这个类是通用的,可以与任何属性一起使用,也支持双向绑定.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读