【问题标题】:Store bindingexpression for later use存储绑定表达式供以后使用
【发布时间】:2015-09-02 06:40:24
【问题描述】:

我有一个使用IsEnabled 绑定的应用程序。 我还需要暂时删除此绑定。

我创建了一个带有附加属性的ControlBehavior,用作临时存储位置。 ClearIsEnabledBinding 将设置此附加属性中使用的绑定。 RestoreIsEnabeldBinding 应该将绑定返回到原始位置。这行不通。当绑定被清除时,附加的属性也被清除。

场景是这样的。我有一个带有 IsEnabled 绑定到带有转换器的视图模型的文本框。当我使用特定函数时,无论视图模型中的值如何,所有 IsEnabled 都应该为真。这很容易,只需删除绑定并设置为 true。但是当我从这个函数返回时,我需要使用转换器将绑定恢复到它与视图模型的原始绑定。所以我需要将整个绑定表达式保存在某个地方,然后将其“放回”

我的班级如下:

对我做错了什么有什么建议吗?

public partial class ControlBehavior
{
    public static readonly DependencyProperty IsEnabledBindingProperty = DependencyProperty.RegisterAttached(
         "IsEnabledBinding",
         typeof(BindingExpression),
         typeof(ControlBehavior),
         new PropertyMetadata(null));

    public static void SetIsEnabledBinding(DependencyObject element, BindingExpression value)
    {
        if (value != null)
        {
            element.SetValue(IsEnabledBindingProperty, value);
            SetIsEnabledBindingSet(element, true);
        }
    }

    public static BindingExpression GetIsEnabledBinding(DependencyObject element)
    {
        var obj = element.GetValue(IsEnabledBindingProperty);
        return (BindingExpression) obj;
    }

    public static readonly DependencyProperty IsEnabledBindingSetProperty = DependencyProperty.RegisterAttached(
        "IsEnabledBindingSet",
        typeof(bool),
        typeof(ControlBehavior),
        new PropertyMetadata(false));

    public static void SetIsEnabledBindingSet(DependencyObject element, bool value)
    {
        element.SetValue(IsEnabledBindingSetProperty, value);
    }

    public static bool GetIsEnabledBindingSet(DependencyObject element)
    {
        return (bool)element.GetValue(IsEnabledBindingSetProperty);
    }


    public static void ClearIsEnabledBinding(DependencyObject element)
    {
        SetIsEnabledBinding(element, ((Control)element).GetBindingExpression(UIElement.IsEnabledProperty));
        ((Control)element).SetBinding(UIElement.IsEnabledProperty, new Binding());
    }

    public static void RestoreIsEnabledBinding(DependencyObject element)
    {
        if (!GetIsEnabledBindingSet(element))
        {
            return;
        }
        ((Control)element).SetBinding(UIElement.IsEnabledProperty, GetIsEnabledBinding(element).ParentBindingBase);
    }
}

【问题讨论】:

  • 你不能使用简单的触发器吗?
  • 我不想在我的视图中添加代码。因为这种行为必须适用于我所有视图的所有控件。
  • IsEnabledBinding 和 IsEnabledBindingSet 属性声明丢失,这反过来又调用了 getproperty 和 setproperty。
  • 我不明白你的意思。
  • 创建依赖属性时,为propertyName定义一个字符串,检查“IsEnabledBindingProperty”定义。

标签: c# wpf binding


【解决方案1】:

我们已经使用下面的类来完成我认为你想要实现的目标:

/// <summary>
/// Utilities to be used with common data binding issues
/// </summary>
class DataBindingUtils

{

    private static readonly DependencyProperty DummyProperty = DependencyProperty.RegisterAttached(

          "Dummy",

          typeof(Object),

          typeof(DependencyObject),

          new UIPropertyMetadata(null));



    /// <summary>
    /// Get a binding expression source value (using the PropertyPath), from MSDN forums:
    /// "Yes, there is one (class to provide the value) inside WPF stack, but it's an internal class"
    /// Get source value of the expression by creating new expression with the same
    /// source and Path, attaching this expression to attached property of type object
    /// and finally getting the value of the attached property
    /// </summary>
    /// <param name="expression"></param>
    /// <returns></returns>
    public static Object Eval(BindingExpression expression)

    {

        // The path might be null in case of expression such as: MyProperty={Binding} - in such case the value we'll get

        // will be the DataContext

        string path = null;

        if (expression.ParentBinding != null && expression.ParentBinding.Path != null)

        {

            path = expression.ParentBinding.Path.Path;

        }



        Binding binding = new Binding(path);

        binding.Source = expression.DataItem;

        DependencyObject dummyDO = new DependencyObject();

        BindingOperations.SetBinding(dummyDO, DummyProperty, binding);

        object bindingSource = dummyDO.GetValue(DummyProperty);

        BindingOperations.ClearBinding(dummyDO, DummyProperty);

        return bindingSource;

    }

}

【讨论】:

  • 嗨。我不需要价值。场景是这样的。我有一个带有 IsEnabled 绑定到带有转换器的视图模型的文本框。当我使用特定函数时,无论视图模型中的值如何,所有 IsEnabled 都应该为真。这很容易,只需删除绑定并设置为 true。但是当我从这个函数返回时,我需要使用转换器将绑定恢复到它与视图模型的原始绑定。所以我需要将整个绑定表达式保存在某个地方,然后“放”回去
  • 所以这就是上面的方法所做的——它复制了现有的绑定,但是用“深拷贝”来做。
  • 它是否处理多重绑定?因为我的一些绑定是多重绑定。
  • 我不确定 - 但您可以扩展它以支持多重绑定
【解决方案2】:

场景是这样的。我有一个带有 IsEnabled 绑定到带有转换器的视图模型的文本框。当我使用特定函数时,无论视图模型中的值如何,所有 IsEnabled 都应该为真。这很容易,只需删除绑定并设置为 true。但是当我从这个函数返回时,我需要使用转换器将绑定恢复到它与视图模型的原始绑定

您可以提供机制来临时覆盖 IsEnabled 值,而不是处理绑定。我假设有 2 个问题:1)您正在绑定某些东西(让我们称之为 IsEnabled)2)您正在制作某种 edit 模式,它应该暂时覆盖绑定值:

bool _isEditMode;
public bool IsEditMode
{
    get { return _isEditMode; }
    set
    {
        _isEditMode = value;
        OnPropertyChanged(nameof(IsEnabled)); // update IsEnabled when IsEditMode changed
    }
}

bool _isEnabled;
public bool IsEnabled
{
    get
    {
        return IsEditMode || _isEnabled; // return true if IsEditMode == true or actual value otherwise
    }
    set
    {
        _isEnabled = value;
        OnPropertyChanged();
    }
}

现在如果你绑定

<TextBox IsEnable="{Binding IsEnabled, Converter= ...}" ... />

那么一旦你设置IsEditMode = true 文本框就会被启用。如果您设置了IsEditMode = false,文本框将根据IsEnabled viewmodel 属性的值再次启用或禁用。

【讨论】:

  • 嗨。我需要忽略绑定并覆盖它以获得不同的行为。完成后,我必须恢复绑定以恢复视图模型的原始行为。
  • 嗨。如果所有 IsEnabled 都绑定到视图模型,那将起作用。我有一些观点认为 IsEnabled 绑定到视图中的其他一些元素。我必须找到一种不改变视图模型或视图的方法。
猜你喜欢
  • 1970-01-01
  • 2017-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多