【问题标题】:Two-Way Binding is not working双向绑定不起作用
【发布时间】:2012-02-14 06:51:27
【问题描述】:

在我的Silverlight 项目中,我正在创建文本框,这些文本框在运行时双向数据绑定 到某个上下文。一个方向(从源到目标)的绑定似乎工作正常,但另一个方向(从目标返回到源)没有显示任何效果.

这是数据上下文:

public class Leg : INotifyPropertyChanged {

    private string passengers;

    public string Passengers {
        get { return passengers; }
        set {
            // here I have a breakpoint.
            passengers = value;
            FirePropertyChanged("Passengers"); 
         }
    }

    private void FirePropertyChanged (string property) {

        if (PropertyChanged != null) {

            PropertyChanged(this, new PropertyChangedEventArgs(property));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

然后在另一个地方我正在创建一个新的 TextBox 控件及其绑定:

Binding passengersBinding = new Binding();

// viewModelLeg is an instance of the class Leg from above    
passengersBinding.Source = viewModelLeg;

passengersBinding.Path = new PropertyPath("Passengers");
passengersBinding.Mode = BindingMode.TwoWay;

legItem.paxTextBox.SetBinding(TextBox.TextProperty, passengersBinding);

现在,当我更改Passengers 字符串的值时,绑定到它的相应文本框正在正确更新其文本。 所以一切都很好。

但是当我手动更改文本框的文本然后使文本框失去焦点时,什么也没有发生 - 即没有发生双向绑定 - 文本框的新文本值不会向下传播到来源!

我在乘客属性的设置器处有一个断点(上面标有断点注释)。 当我把这一切都做好时,绑定引擎也会在绑定的目标值发生变化时使用这个公共设置器来更新源——所以当这种情况发生时,必须命中断点。 但他没有!所以看来我可以用我的文本框做我想做的事(玩焦点或按Enter)它永远不会更新它的源代码。

我在监督什么吗?在我的代码或我的想法中一定有一个大写错误..我会非常感谢任何想法......

编辑:

在下面,我尝试演示如何创建我的 XAML 对象和我的 DataContext 对象。因为我在运行时创建 XAML 控件及其绑定,所以我还没有找到一个很好的解决方案来很好地实现 MVVM 方法。所以我正在做以下事情(这可能不是最好的方法):

我正在建模的情况是我有一个 UserControl(称为 LegItem),它(主要)由文本框组成。在运行时,用户可以根据自己的意愿(一个接一个)创建尽可能多的这些用户控件。

在我的 ViewModel 方面,我有一个类(称为 Leg),它正好用作一个 LegItem 的 ViewModel。因此,当我说 n (XAML-) LegItems 时,我也有 n Leg 实例。我将这些 Leg 对象存储在 List 中。

因此,每次用户单击“添加新腿”按钮时,我都会执行以下操作:

// here we are inside the applications view in an .xaml.cs file

public void AddLeg () {

    // this is going to serve as the ViewModel for the new LegItem
    // I am about to create.
    Leg leg = viewModel.insertLeg();

    // here I am starting to create the visual LegItem. The ViewModel object
    // I have created in the previous step is getting along with.
    createLegItem(leg);
}

// the primary job here is to bind each contained textbox to its DataContext.
private LegItem createLeg (Leg viewModelLeg) {

    // create the visual leg item control element
    // which is defined as a XAML UserControl.
    LegItem legItem = new LegItem();

    Binding passengersBinding = new Binding();

    // viewModelLeg is an instance of the class Leg from above    
    passengersBinding.Source = viewModelLeg;

    passengersBinding.Path = new PropertyPath("Passengers");
    passengersBinding.Mode = BindingMode.TwoWay;

    legItem.paxTextBox.SetBinding(TextBox.TextProperty, passengersBinding);

}


// on the viewModel side there is this simple method that creates one Leg object
// for each LegItem the View is creating and stores inside a simple list.

public Leg InsertLeg () {

    Leg leg = new Leg();
    legList.add(leg)

    return leg;
}

【问题讨论】:

  • 当您说“手动更改文本框的文本”时,您是指在文本框中输入内容还是设置SomeTextBox.Text = "SomeValue"?因为第二种方式是覆盖绑定,所以TextBox.Text属性不再绑定。
  • 您是否也在 xaml 中设置绑定?如果是这样,您的 xaml 绑定可能会覆盖您的自定义绑定。 (取决于上面的代码所在的位置)
  • @Rachel:不,我采用第一种方法。用我的光标选择文本框,在其中写入一些文本,然后单击另一个控件,使文本框失去焦点。
  • @Marc 您的绑定代码工作正常,因此它必须与您绑定数据的方式有关。您能否创建一个单独的项目并重新创建一个演示问题的小示例?
  • @Marc 你能显示LegItem,尤其是paxTextBox 的XAML 吗?

标签: c# wpf silverlight data-binding binding


【解决方案1】:

新答案

由于您提到您的绑定实际上是自定义 UserControl 而不是 TextBox,因此我建议您查看 UserControl 的 XAML 并确保它正确绑定数据


旧答案

我对一个新的 Silverlight 项目进行了快速测试,发现启动项目是 SilverlightApplication1.Web,而不是 SilverlightApplication。

这意味着当我运行项目时,setter 中的断点实际上不会受到影响。你会注意到断点圆圈只是轮廓,并没有填充颜色。如果你将鼠标悬停在它上面,它会说

当前不会命中断点。未加载任何符号 对于这个文件

如果我启动 SilverlightApplication1 而不是 .Web 版本,断点会被命中。

无论我启动哪个版本,属性都会正确更改,但是如果我使用.Web 版本启动项目,断点不会受到影响。我怀疑这是你的问题。

【讨论】:

  • Rachel,非常感谢您在我的问题上花费了这么多精力。当我设置断点并进入我的 ViewModel 类时,我可以看到我的数据值确实没有改变。这让我相信绑定真的没有向下工作。同样,当我更改此 ViewModel 类中的某些数据值时,正确的文本框会检索正确的更改,这使我相信每个文本框都通过正确的绑定链接到正确的数据属性。再次感谢您!
  • @Marc 您如何验证在 TextBox 中输入的数据没有保存到数据对象中?我开始使用断点,但注意到它没有被击中。然后我创建了一个绑定到同一个数据项的第二个文本框,并注意到当我更新任何一个时,两者都得到了更新。
  • 好的,我想我明白你的意思了。我正在执行以下操作来验证:我只是在位于我的 ViewModel 类中的 InsertLeg() 方法上放置一个断点。所以每次我添加 LegItem 时都会调用此方法以生成新的“ViewModel-Leg”和将它放在一个列表中。所以我添加了一些新的 LegItems,更改了一些文本框的值,单击添加,这会导致列表所在的 ViewModel 内的执行暂停。然后我查看列表并注意到所有 Leg - 对象都未修改,尽管我刚刚更改了一些绑定到它们的某些属性的文本框
  • @Marc 这让我认为被绑定的项目与列表中的项目引用不完全相同。当您测试更新数据值时,您是否以相同的方式进行操作?例如,在您的 InsertLeg() 方法中,更新集合中的一项并查看它是否更新 UI 中的 TextBlock。
  • Rachel,我真的要道歉,因为我刚刚发现了错误。从一开始你就是对的——错误与绑定或 View-ViewModel 架构的设置无关。顺便说一句,关于你的最后一条评论:我确实按照你描述的方式验证了它:) 让我们俩都有些头疼的错误(希望你的没有我的微笑那么强烈)在于TextBox 本身:它不是默认的 clr TextBox,而是我的一个更改版本 - userControl,它在其 ControlTemplate 中包含一个 TextBlock 和一个 TextBox。 [继续...
猜你喜欢
  • 2014-04-10
  • 2011-10-14
  • 2014-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-11
相关资源
最近更新 更多