【发布时间】: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