我正在编写一个值输入控件,可以随处使用。控件本身有一个视图模型,它像往常一样设置为DataContext。但是当我在父控件中使用控件时,如:
<UserControl x:Class="X.Y.Z.ParentControl">
...
<local:ValueInput Value="{Binding Path=MyValue}" />
...
</UserControl>
我要将MyValue
ParentControl
的{{1}}属性绑定到DataContext
控件,但是WPF告诉我它找不到ValueInput
MyValue
类中的属性,它是ValueInputViewModel
控件本身的视图模型。为什么WPF正在寻找孩子ValueInput
的价值?
我只想编写一个可以像这样使用的控件:
DataContext
<telerik:RadNumericUpDown Value="{Binding Path=NumberValue}" />
属性在父级NumberValue
中定义,而不在控件中定义。这种模式适用于teleriks控制,但不适用于我的控制。
我该怎么办?
答案 0 :(得分:1)
对于任何FrameworkElement,只能有一个DataContext。
如果UserControl有自己的DataContext,则它不能使用父的DataContext。
但是,您可以使用RelativeSource
走到父级并获取其DataContext(每次需要引用Parent的DataContext时)Binding="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type Window}}, Path=DataContext.NumberValue}"
要使此示例起作用,Parent(任何级别的root)应为Window。如果是UserControl,
Binding="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type UserControl}}, Path=DataContext.NumberValue}"
代码来自this link
提供的fiq答案 1 :(得分:0)
我的朋友告诉我不要在独立控件中使用DataContext
作为视图模型,因为DataContext很容易被覆盖 - 定义ViewModel
属性并在XAML中绑定可以解决问题。这是一个例子:
查看模型类:
public class MyValueInputViewModel
{
public string MyText { get; set; }
}
代码背后:
public partial class MyValueInput : UserControl
{
public MyValueInput()
{
InitializeComponent();
this.ViewModel = new MyValueInputViewModel
{
MyText = "Default Text"
};
}
public static readonly DependencyProperty ViewModelProperty =
DependencyProperty.Register("ViewModel", typeof(MyValueInputViewModel), typeof(MyValueInput));
public MyValueInputViewModel ViewModel
{
get
{
return (MyValueInputViewModel)this.GetValue(ViewModelProperty);
}
private set
{
this.SetValue(ViewModelProperty, value);
}
}
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value", typeof(string), typeof(MyValueInput), new PropertyMetadata(OnValuePropertyChanged));
private static void OnValuePropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs args)
{
var input = (MyValueInput)o;
input.ViewModel.MyText = input.Value;
}
public string Value
{
get { return (string)this.GetValue(ValueProperty); }
set { this.SetValue(ValueProperty, value); }
}
}
XAML:
<UserControl x:Class="..." x:Name="Self" ...>
<Grid>
<TextBox Text="{Binding ViewModel.MyText, ElementName=Self, UpdateSourceTrigger=PropertyChanged}" />
</Grid>
</UserControl>