【问题标题】:Changing binding mode in code?在代码中更改绑定模式?
【发布时间】:2017-12-02 12:34:27
【问题描述】:

我正在制作一个小型应用程序,它是一个从数据源读取的表单,我想用它来编辑和添加新记录。 因此,表单中文文本框的默认绑定模式是TwoWay mode,因此用户可以编辑现有记录,但是我要添加一个复选框,在选中后,它将文本框中的数据标记为新的,然后添加他们到数据源,所以我需要将绑定模式更改为OneWay, 据我所知,要在代码中执行此操作,我需要创建一个新的 Binding 对象,我必须设置像 Source 这样不会改变的属性:

Binding myBinding = new Binding();
myBinding.Source = ViewModel;
myBinding.Path = new PropertyPath("SomeString");
myBinding.Mode = BindingMode.TwoWay;
myBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;

那么有没有办法只改变代码中的Binding模式呢?

编辑

对应用程序的一些进一步解释:

在表单中有一个绑定到List<Book> 的组合框,有3 个TextBoxs,它们的Text 属性绑定到其容器的DataContext 对象,该对象本身设置为SelectedItem Combobox。 当我按照答案中的描述添加ReadOnly 属性时,当我选中复选框时,我无法更改文本框中的文本。

..

谢谢!

【问题讨论】:

  • 你是对的,你需要创建新的绑定。但。您能解释一下为什么要在代码隐藏中执行此操作吗?您可以在查看复选框 IsChecked 值的触发器中设置 XAML 中的新绑定。另外我确定您不需要更改绑定的Mode。让它成为TwoWay,但当绑定到IsChecked 的某些属性等于true 时,不要更新支持字段。
  • 很有趣,您能否将其作为答案发布,并附上代码示例?
  • 好的,我已经发布了。

标签: c# wpf data-binding binding-mode


【解决方案1】:

对此的回答是“是的,但是”。 Binding 的 Mode 属性有一个 setter。因此,您似乎可以像这样设置现有绑定的模式...

       BindingExpression be = textBox.GetBindingExpression(TextBox.TextProperty);
        Binding b = be?.ParentBinding as Binding;
        if (b != null)
        {
            b.Mode = BindingMode.OneWay;
        }

但是,如果您这样做,您将在每种情况下都会遇到异常...

System.InvalidOperationException occurred
HResult=0x80131509
Message=Binding cannot be changed after it has been used.

因此,完成您想要的唯一方法是在更改模式的同时基于旧绑定创建新绑定。然后替换旧的绑定。

           BindingExpression be = textBox.GetBindingExpression(TextBox.TextProperty);
        Binding b = be?.ParentBinding as Binding;
        if (b != null)
        {
            Binding b2 = new Binding();
            b2.Path = b.Path;
            b2.Mode = BindingMode.OneWay;
            textBox.SetBinding(TextBox.TextProperty, b2);
        }

这不太理想,因为为了完整起见,您需要复制转换器、转换器参数等,但这是您能做的最好的。

【讨论】:

    【解决方案2】:

    不要更改绑定的Mode。只需更正您的视图模型逻辑即可。

    public class ViewModel : INotifyPropertyChanged
    {
        private string _text;
        private bool _readOnly;
    
        public string Text
        {
            get { return _text; }
            set
            {
                if (ReadOnly || value == _text)
                    return;
    
                _text = value;
                OnPropertyChanged(nameof(Text));
            }
        }
    
        public string ReadOnly
        {
            get { return _readOnly; }
            set
            {
                if (value == _readOnly)
                    return;
    
                _readOnly = value;
                OnPropertyChanged(nameof(ReadOnly));
            }
        }
    }
    

    在 XAML 中,将 CheckBoxIsChecked 属性绑定到 ReadOnly 属性。

    【讨论】:

    • 它不会更新 UI 但仍然绑定到源
    • 是的。它有什么问题?它可以在不更改绑定的情况下解决您的任务。如果此解决方案不合适,请说明原因。
    • 我把setter改成了这个,if (title == value) return; title = value; if (ReadOnly) return; OnPropertyChanged(nameof(Title));请看修改后的问题
    • 好的...但据我了解,您希望在ReadOnly == true 的情况下阻止源更新。我做出这个决定是因为您打算使用Mode=OneWay。现在看来你无论如何都想更新源,你只需要阻止 UI 更新。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-07-25
    • 2018-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多