[英]How to parametrize binding in wpf UserControl?
我有一个wpf窗口( MyWindow
),其DataContext
设置为MyViewModel
视图模型类:
<Window x:Class="MyProject.MyWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d">
<MyUserControl Text="{Binding MyText, Mode=TwoWay}" />
</Window>
public class MyWindow : Window
{
MyWindow()
{
InitializeComponent();
DataContext = new MyViewModel();
}
}
// MyViewModel implements IPropertyChanged
public class MyViewModel : INotifyPropertyChanged
{
public string MyText { get { ... } set { ... } }
...
}
我想将MyText
属性的绑定从MyWindow
传递给以下UserControl( MyUserControl
):
<UserControl x:Class="MyProject.MyUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d">
<StackPanel>
<TextBox
Name="MainTextBox"
Text="{Binding Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, NotifyOnValidationError=True}"
/>
</StackPanel>
</UserControl>
public partial class MyUserControl : UserControl
{
public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
"Text",
typeof(string),
typeof(MyUserControl),
new UIPropertyMetadata(TextPropertyChangedHandler)
);
public static void TextPropertyChangedHandler(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
var MyUserControl = sender as MyUserControl;
MyUserControl.Text = (string)e.NewValue;
}
public string Text
{
get
{
return (string)GetValue(TextProperty);
}
set
{
SetValue(TextProperty, value);
}
}
public MyUserControl()
{
InitializeComponent();
}
}
我想将在MyUserControl
下的Textbox
键入的内容放入MyViewModel.MyText
。 如何做到这一点?
我试图绑定MyText
到Text
的属性MyUserControl
并随后绑定Text
在TextBox
以Text
从MyUserControl
但这不起作用。
摆脱TextPropertyChangedHandler
。
DP仅需要BindsTwoWayByDefault
标志,而无需回调
public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
"Text",
typeof(string),
typeof(MyUserControl),
new FrameworkPropertyMetadata(null,
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault)
);
TextBox.Text
应该绑定到MyUserControl.Text
<UserControl x:Class="MyProject.MyUserControl" x:Name="self"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d">
<StackPanel>
<TextBox Text="{Binding Text, Mode=TwoWay, ElementName=self}" />
</StackPanel>
</UserControl>
验证属性应转到Window中的绑定:
<MyUserControl Text="{Binding MyText, Mode=TwoWay, ValidatesOnDataErrors=True, NotifyOnValidationError=True}" />
我终于设法以编程方式从UserControl绑定到视图模型中的属性。
MyUserControl
的用法如下:
<UserControls:MyUserControl TargetPropertyName="TestId"/>
我只是将希望绑定到的View模型的属性名称传递给用户控件。
然后,在用户控件中,我确保以编程方式通过MainTextBox
上的名称绑定属性(在此处为BindTextPropertyToTargetPropertyNameOnce
):
public partial class MyUserControl : UserControl
{
public static readonly DependencyProperty TargetPropertyNameProperty = DependencyProperty.Register(
"TargetPropertyName",
typeof(string),
typeof(MyUserControl),
new UIPropertyMetadata(TargetPropertyNamePropertyChangedHandler)
);
public static void TargetPropertyNamePropertyChangedHandler(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
var MyUserControl = sender as MyUserControl;
MyUserControl.TargetPropertyName = (string)e.NewValue;
}
public string TargetPropertyName
{
get
{
return (string)GetValue(TargetPropertyNameProperty);
}
set
{
SetValue(TargetPropertyNameProperty, value);
BindTextPropertyToTargetPropertyNameOnce()
}
}
public MyUserControl()
{
InitializeComponent();
}
private bool _firstRun = true;
private void BindTextPropertyToTargetPropertyNameOnce()
{
if (_firstRun)
{
_firstRun = false;
var binding = new Binding(TargetPropertyName)
{
Mode = BindingMode.TwoWay,
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,
ValidatesOnDataErrors = true,
NotifyOnValidationError = true
};
MainTextBox.SetBinding(TextBox.TextProperty, binding);
}
}
}
但是我仍然认为这是一种解决方法,必须有更好的解决方案。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.