我正在处理的应用程序要求限制绑定到多行TextBox的字符串中的行数和每行字符。这些限制可以在应用程序运行时更改。绑定到TextBox的viewmodel属性是一个字符串列表。应该防止用户输入超出限制的字符。
我创建了一个IMultiValueConverter,它可以完成两件事:1)使用Environment.NewLines将字符串列表转换为单个字符串,并在列表的元素之间添加2)根据用户类型将行和字符限制在一行。
这是我的转换器;绑定参数是字符串列表,最大行数和每行最大字符数:
public class MultiLineTextConverter : IMultiValueConverter
{
private int MaxLines { get; set; }
private int MaxCharactersPerLine { get; set; }
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (!(values[1] is int maxLines) || !(values[2] is int maxCharactersPerLine))
{
return DependencyProperty.UnsetValue;
}
MaxLines = maxLines;
MaxCharactersPerLine = maxCharactersPerLine;
if (!(values[0] is IEnumerable<string> lines))
{
return DependencyProperty.UnsetValue;
}
return string.Join(Environment.NewLine, ClampLines(lines));
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
var text = (string) value;
var lines = text.Split(new[] {Environment.NewLine}, StringSplitOptions.None);
return new[] {ClampLines(lines), Binding.DoNothing, Binding.DoNothing};
}
private List<string> ClampLines(IEnumerable<string> lines)
{
return lines.Take(MaxLines).Select(l => l.Substring(0, Math.Min(l.Length, MaxCharactersPerLine))).ToList();
}
}
转换器在视图中的使用方式如下(转换器资源定义为x:Shared =“ False”,因为它对ConvertBack使用字符串限制状态):
<TextBox
TextWrapping="Wrap"
AcceptsReturn="True">
<TextBox.Text>
<MultiBinding
UpdateSourceTrigger="PropertyChanged"
Converter="{StaticResource MultiLineTextConverter}">
<Binding
Mode="TwoWay"
Path="TextLines" />
<Binding
Path="LineLimit"
Mode="OneWay" />
<Binding
Source="{StaticResource CharactersPerLine}"
Mode="OneTime" />
</MultiBinding>
</TextBox.Text>
</TextBox>
并且viewmodel属性为:
private IReadOnlyCollection<string> _textLines;
public IReadOnlyCollection<string> TextLines
{
get => _textLines;
set
{
_textLines= value;
OnPropertyChanged();
}
}
除一种情况外,转换器的运行效果非常好。如果最大行数为3,我可以输入:
A
B
C
,它阻止我在“ C”之后点击return。但是,如果我将光标放在B后面并按回车键,则转换器会将其转换回:
A
B
\r\n
将其正确设置为viewmodel属性设置器,从而引发INPC,这将导致调用viewmodel属性getter,该方法返回正确的值,然后通过Convert方法返回:
A
B
\r\n
因此,正确的值最终会使整个往返行程正确进行,就像您键入的任何其他值一样,但是视图仍显示:
A
B
\r\n
C
真正让我感到奇怪的是,如果我将Snoop附加到应用程序并检查视图,则数据上下文看起来正确(AB\r\n
),而一旦检查了TextBox,视图就会刷新并看起来正确。从那时起,即使没有附加Snoop,它也可以正常工作。
我不经常这样说,但是这次我要使用“这看起来像是框架中的错误”的老板栗。但是,我想知道是否有解决方法,或者这是TextBox的已知错误。除此之外,我可能会将功能分解为附加行为和转换器。