我有ViewModel
public class VM: DependencyObject, INotifyPropertyChanged
{
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
// Using a DependencyProperty as the backing store for Text. This enables animation, styling, binding, etc...
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(string), typeof(VM), new PropertyMetadata(""));
public int Length
{
get
{
return Text != null ? Text.Length : 0;
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
并查看它
<UserControl.DataContext>
<local:VM Text="{Binding ControlText, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}"/>
</UserControl.DataContext>
<StackPanel>
<TextBox Text="{Binding Text, UpdateSourceTrigger=PropertyChanged}"/>
<TextBlock Text="{Binding Length}"/>
</StackPanel>
是的,view在代码后面还有依赖属性
public string ControlText
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
// Using a DependencyProperty as the backing store for Text. This enables animation, styling, binding, etc...
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("ControlText", typeof(string), typeof(Writer), new PropertyMetadata(""));
输出日志出错了
System.Windows.Data错误:4:无法找到绑定源,引用'RelativeSource FindAncestor,AncestorType ='System.Windows.Controls.UserControl',AncestorLevel ='1''。 BindingExpression:路径= ControlText;的DataItem = NULL; target元素是'VM'(HashCode = 21019086); target属性是'Text'(类型'String')
当这项技术有效时,我将拥有构建我的viewmodel的工具。 也许有人知道如何将这个视图属性绑定到viewmodel属性或知道技术如何正确地执行它:)
答案 0 :(得分:1)
你似乎对某些事情感到困惑。如果要将视图模型设置为XAML中的UserControl.DataContext
,那没关系,但是没有数据绑定到那里的控件:
<UserControl.DataContext>
<local:VM />
</UserControl.DataContext>
接下来,如果视图模型设置为UserControl.DataContext
,那么您可以从UserControl
中的XAML访问其属性,如下所示:
<StackPanel>
<TextBox Text="{Binding Text, UpdateSourceTrigger=PropertyChanged}"/>
<TextBlock Text="{Binding Length}"/>
</StackPanel>
现在,如果您想从XAML访问ControlText
属性,那么 就是您需要使用RelativeSource Binding
的时候。但是,请注意您应该如何使用UserControl
引用UserControl
的名称/类型和而不是,因为正如您的错误所述,没有定义ControlText
属性在UserControl
。试试这个:
<StackPanel>
<TextBox Text="{Binding ControlText, RelativeSource={RelativeSource
AncestorType={x:Type local:YourUserControl}} />
<TextBlock Text="{Binding Length}"/>
</StackPanel>
最后,如果您希望数据绑定到控件的<{1>}属性 outside 控件,那么您可以这样做:
ControlText
更新&gt;&gt;&gt;
使用MVVM时,我们通常不尝试将数据从一个数据源通过<local:YourUserControl ControlText="{Binding SomeStringProperty}" />
传递到另一个数据源。相反,我们更喜欢将数据从一个数据项传递到另一个数据项。您的问题是您在视图中实例化视图模型...而是在父视图模型中实例化它并传入您想要的任何值,然后将其设置为外部的UIElement
属性值父视图中的控件:
UserControl.DataContext
在视图模型中获得正确的值后,您就不需要<local:YourUserControl DataContext="{Binding YourChildViewModelPropertyInParentVM}" />
属性。
答案 1 :(得分:0)
如果在XAML中声明DataContext
,它将在XAML加载时初始化。此外,VM
不像UserControl那样位于Visual Tree中,因此RelativeSource
无法在此处工作。
但是你可以在后面的代码中通过从UserControl的构造函数设置DataContext并在那里自己绑定来实现:
public MainWindow()
{
InitializeComponent();
VM viewModel = new VM();
DataContext = viewModel;
Binding binding = new Binding("ControlText") { Source = this };
BindingOperations.SetBinding(viewModel, VM.TextProperty, binding);
}