假设我有texbox和textblock:
<TextBox Name="textBox1"
Text="{Binding Path=user,
RelativeSource={RelativeSource FindAncestor,
AncestorType=my:MainWindow, AncestorLevel=1},
Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<TextBlock Name="textBlock1"
Text="{Binding Path=user,
RelativeSource={RelativeSource FindAncestor,
AncestorType=my:MainWindow, AncestorLevel=1},
Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
代码背后:
private string _user = "a";
public string user
{
get
{
return _user;
}
set
{
if (!String.IsNullOrEmpty(value.Trim()))
_user = value;
//else
//_user = _user + Environment.NewLine;
NotifyPropertyChanged("user");
}
}
我想要实现的目标 - 不允许用户在文本框和文本块中输入空字符串(或空格)。如果文本为空 - 我只是恢复以前的值(由用户文本清除 - 在我的代码的情况下为“a”)。
上面的代码适用于textblock,但不适用于textbox(在文本框中按退格键后的屏幕截图):
此外,如果您从
中删除评论 //else
//_user = _user + Environment.NewLine;
一切都像魅力一样(我需要恢复以前的值,而不是使用Environment.NewLine :),当然这是
那发生了什么事?为什么文本框的行为与预期的差异很大(甚至与文本块行为不同)?
更新
我期待的是什么:
如果我在文本框中按退格键,则表达式!String.IsNullOrEmpty(value.Trim())
为false。
_user
未更新(仍为“a”)。
在下一行调用NotifyPropertyChanged("user")
会强制绑定得到“a”(如果我在getter中触发断点,则_user
等于“a”,如预期的那样。)
但正如您在屏幕截图中看到的那样 - 文本框由于某种原因是空的。
答案 0 :(得分:1)
我不会称之为任何类型的错误。造成这种差异是因为TextBox
可以从两个地方更改,而TextBlock
只能从一个地方更改。该一个来源的规则不允许该值为空string
,因此,它不会显示空的string
。另一方面,TextBox
没有这样的规则来阻止用户更改值。为此,您需要为TextBox.PreviewKeyDown
事件添加处理程序:
<TextBox Name="textBox1" Text="{Binding Path=user, RelativeSource={RelativeSource
AncestorType=my:MainWindow}, UpdateSourceTrigger=PropertyChanged}"
PreviewKeyDown="TextBox_PreviewKeyDown"/>
...
private void TextBox_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (((TextBox)sender).Text.Trim().Length == 1 &&
(e.Key == Key.Delete || e.Key == Key.Back)) e.Handled = true;
}
另请注意,您无需在RelativeSource Binding
中设置其中一半属性......上述内容应该相同。 TextBox.TextProperty DependencyProperty
在其默认BindsTwoWayByDefault
中设置了FrameworkMetadata
标记,因此您无需在此使用Mode=TwoWay
,只需设置AncestorType
即可属性。
答案 1 :(得分:0)
我遇到过同样的问题 当人们告诉我他们无法复制时,我就会想到环境 对我来说,它不适用于.NET 3.5或.NET 4.0,但它适用于.NET 4.5 答案是在.NET 4.5上试试
这是一种设置DataContext的XAML方式 没有理由在TextBlock上使用TwoWay或UpdateSourceTrigger
DataContext="{Binding RelativeSource={RelativeSource self}}"
Title="MainWindow" Height="350" Width="525">
<Grid>
<StackPanel Orientation="Vertical">
<TextBox Text="{Binding TextNoEmpty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<TextBlock Text="{Binding TextNoEmpty, Mode=OneWay}"/>
</StackPanel>
</Grid>
在.NET 3.5上测试了上面的内容并重现了问题 在.NET 4.5上测试了上面的内容并且它正常工作
如果您尝试在setter中截断到最大长度,则可能会出现同样的问题。