我有一个非常类似的问题,如this post中所述。
我有一个UserControl来封装一个地址。它包含许多基本控件,主要是文本框。然后,我在代码隐藏中为每个属性提供了依赖属性...
#region Line1
/// <summary>
/// Gets or sets the Line1.
/// </summary>
public string Line1
{
get
{
return (string)GetValue(Line1Property);
}
set
{
SetValue(Line1Property, value);
}
}
/// <summary>
/// The Line1 dependency property.
/// </summary>
public static readonly DependencyProperty Line1Property =
DependencyProperty.Register(
"Line1",
typeof(string),
typeof(AddressControl),
new PropertyMetadata(OnLine1PropertyChanged));
/// <summary>
/// Line1Property property changed handler.
/// </summary>
/// <param name="d">AddressControl that changed its Line1.</param>
/// <param name="e">DependencyPropertyChangedEventArgs.</param>
private static void OnLine1PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = d as AddressControl;
if (control != null)
{
control.OnLine1Changed((string)e.OldValue, (string)e.NewValue);
}
}
/// <summary>
/// Called when the Line1 changes.
/// </summary>
/// <param name="oldValue">The old value.</param>
/// <param name="newValue">The new value.</param>
private void OnLine1Changed(string oldValue, string newValue)
{
Line1TextBox.Text = newValue;
}
#endregion Line1
然后我在视图中使用此控件...
<myControls:AddressControl Grid.Row="0" Grid.Column="3"
Line1="{Binding Path=Line1, Mode=TwoWay}"/>
这似乎是在视图模型属性更新时设置文本框值,但是我的问题是从usercontrol获取更新回到viewmodel?
根据上面的链接,我应该在控件上检查我的DataContext。 Surley的DataContext将与父级相同吗?
我希望对此的答案适用于多个嵌套级别的控件,即。 Control1中使用的Control1在Control3中使用,整个可重用性点!
让我疯了所以任何帮助都非常感激。
答案 0 :(得分:3)
在MVVM中,您应该绑定到ViewModel属性,而不是绑定到控件的代码隐藏中定义的属性
答案 1 :(得分:0)
我认为我最初并没有很好地解释自己,也认为我找到了解决方案。
对于其他人;我的目标是创建一个简单的用户控件来封装一个地址(第1-4行和邮政编码,告诉你它很简单)由TextBoxes组成,用于许多页面(有时在同一页面上使用多次)。这些页面(视图)中的每一个都由MVVM模式中的ViewModel支持。到目前为止,这都是标准。我无法弄清楚的是如何更改任何这些文本框以推进到包含AddressControl的页面的ViewModel。和我在一起?
事实证明,解决方案(现在看来显而易见)是处理每个文本框丢失的焦点并更新依赖属性,这会导致绑定触发到视图模型。
private void AddressTextBox_LostFocus(object sender, RoutedEventArgs e)
{
switch (((TextBox)sender).Name)
{
case "Line1TextBox":
Line1 = Line1TextBox.Text;
break;
case "Line2TextBox":
Line2 = Line2TextBox.Text;
break;
case "Line3TextBox":
Line3 = Line3TextBox.Text;
break;
case "Line4TextBox":
Line4 = Line4TextBox.Text;
break;
case "LinePostcodeTextBox":
Postcode = PostcodeTextBox.Text;
break;
}
}
另一种选择是将文本框绑定到控件代码隐藏中的后备ViewModel,并对此更改控件。使用本地绑定而不是处理事件的效果相同。
答案 2 :(得分:0)
看起来像UserControl背后的代码用于提供控件本身绑定的属性。在这种情况下,您可能会得到一些代码,例如“this.DataContext = this”或“this.AddressLine1Control.DataContext = this”,这可能会有问题(甚至会导致SL2崩溃)。创建一个单独的类来保存数据属性,然后执行类似“this.DataContext = new MyAddressClass()”的操作。您会注意到DataContext一直向下传播到控制树,以便嵌套控件继承其父级的DataContext,如您所愿。
此外,在这里看起来您不需要DependencyProperties。创建传统的CLR属性并在数据类上实现INotifyPropertyChanged接口会更简单(假设您将数据与UserControl类分开)。这是在SL2中进行数据绑定的标准和推荐方法。