我对WPF中的数据绑定很新,我遇到了自定义Textbox / Label和TwoWay数据绑定的问题。可以通过数据绑定设置Text属性,但是当用户更改Text时,绑定doesent会更新source属性。
首先,我的对象包含source属性:
public class DataObject {
public string MyString { get; set; }
}
然后我有我的自定义UserControl。此UserControl的用途基本上是在单击时显示文本框,因此用户可以更改该值。
....
<DockPanel >
<Label Name="Label" MouseLeftButtonDown="EditText" Style="{StaticResource InputLabel}" Content="{Binding Path=Text, RelativeSource={RelativeSource FindAncestor, AncestorType=MyNamespace:MyCustomLabel, AncestorLevel=1},Mode=TwoWay}" ></Label>
<TextBox Name="TextBox" Style="{StaticResource TextBox}" Visibility="Collapsed" HorizontalAlignment="Left" HorizontalContentAlignment="Left" />
</DockPanel>
....
MyCustomLabel.Xaml.cs:
public partial class MyCustomLabel : UserControl {
private static readonly DependencyProperty TextProperty=DependencyProperty.Register("Text",typeof(string),typeof(MyCustomLabel));
public MyCustomLabel() {
InitializeComponent();
}
public string Text {
get {
if (TextBox.Visibility==Visibility.Visible) {
return (string)GetValue(MyCustomLabel.TextProperty);
} else {
return Label.Content.ToString();
}
} set {
base.SetValue(MyCustomLabel.TextProperty,value);
}
}
private void EditText(object sender,MouseButtonEventArgs e) {
TextBox.Visibility=Visibility.Visible;
Label.Visibility=Visibility.Collapsed;
Dispatcher.BeginInvoke((ThreadStart)delegate {
TextBox.Focus();
TextBox.SelectionStart=TextBox.Text.Length;
});
}
}
所以这将是当前的流程:
1.初始化Dataobject,并设置MyString属性
2.保存MyCustomLabel的用户控件初始化为
3.绑定工作,MyString属性显示在标签
中
4.用户单击Label,TextBox现在显示,用户更改值
5.用户单击保存按钮,内容应该保存,但MyString属性不会使用新值更新
如果我调试并访问MyCustomLabel.Text,则属性已正确更改
我尝试在每个类中实现INotifyPropertyChanged,但这没有任何效果。
希望你能提供帮助:)
-------编辑:------
非常感谢您的回答。它指出了我正确的方向
@Sheridan:
我没有单个文本框具有只读状态的原因是我需要Label的功能和布局,直到单击标签并且文本框变得可见。不过,我可能会改变自己的方式。
无论如何,我通过将Label绑定到Textbox.Text来解决它,然后将Textbox.Text绑定到控件Text属性,如下所示:
<DockPanel >
<Label Name="Label" MouseLeftButtonDown="EditText" Style="{StaticResource InputLabel}" Content="{Binding ElementName=TextBox, Path=Text}" ></Label>
<TextBox Name="TextBox" Style="{StaticResource TextBox}" Visibility="Collapsed" HorizontalAlignment="Left" HorizontalContentAlignment="Left" Text="{Binding Text, RelativeSource={RelativeSource AncestorType=MyNamespace:MyCustomLabel},Mode=TwoWay}" />
</DockPanel>
答案 0 :(得分:3)
基本上是为了&#34;第二&#34;您需要实现INotifyPropertyChanged并从您的属性设置器中手动触发事件的方式(即从UI到绑定的非UI端)。另一种方法是使用DependencyProperty,但它被许多人认为是一种矫枉过正(包括我自己)。
这里有一些原型代码:
如果您只需要将一个UI元素绑定到另一个UI元素,那么您可能会使用ElementName =&#39; ...&#39;相关绑定中的路径和路径(在这种情况下你会变得无代码,这太酷了。)
答案 1 :(得分:1)
你显然有一些问题。首先,您不能将Label
与TwoWay Binding
一起使用,因为它不提供任何数据输入方法,例如TextBox
。因此,这是不正确的:
<Label Name="Label" MouseLeftButtonDown="EditText" Style="{StaticResource InputLabel}"
Content="{Binding Path=Text, RelativeSource={RelativeSource FindAncestor,
AncestorType=MyNamespace:MyCustomLabel, AncestorLevel=1},Mode=TwoWay}" ></Label>
其次,您未在Binding
属性上设置TextBox.Text
:
<TextBox Name="TextBox" Style="{StaticResource TextBox}" Visibility="Collapsed"
HorizontalAlignment="Left" HorizontalContentAlignment="Left" />
通常,最好使用一个只读和可编辑状态的控件,而不是像你一样使用两个控件。 TextBox
是完美的,因为它有IsReadOnly
Property。因此,您只需显示一个TextBox
并切换IsReadOnly
属性,而不是其他控件的Visibility
:
<TextBox Name="TextBox" Style="{StaticResource TextBox}" Visibility="Collapsed"
HorizontalAlignment="Left" HorizontalContentAlignment="Left" Text="{Binding Text,
RelativeSource={RelativeSource AncestorType={MyNamespace:MyCustomLabel}}}"
IsReadOnly="{Binding IsReadOnly, RelativeSource={RelativeSource AncestorType={
MyNamespace:MyCustomLabel}}}" />
当然,您需要向IsReadOnly DependencyProperty
添加新UserControl
,并在EditText
方法中更新{<1}}:
private void EditText(object sender,MouseButtonEventArgs e) {
IsReadOnly = false;
}
请注意,无需在TwoWay Binding
属性上设置TextBox.Text
,因为它设置了FrameworkPropertyMetadata.BindsTwoWayByDefault
属性。来自MSDN上的TextBox.Text
Property页:
希望您现在可以设法完成控制。