我有一个控件,它最基本的级别是一个带有 StackPanel(方向=垂直)的 ScrollViewer,其中有很多 TextBox。
<ScrollViewer>
<StackPanel x:Name="MyStackPanel"
Orientation="Vertical">
<TextBox Text="{Binding PropertyA, ValidatesOnDataErrors=True}" />
<TextBox Text="{Binding PropertyB, ValidatesOnDataErrors=True}" />
<TextBox Text="{Binding PropertyC, ValidatesOnDataErrors=True}" />
<!-- ... -->
<TextBox Text="{Binding PropertyX, ValidatesOnDataErrors=True}" />
<TextBox Text="{Binding PropertyY, ValidatesOnDataErrors=True}" />
<TextBox Text="{Binding PropertyZ, ValidatesOnDataErrors=True}" />
</StackPanel>
</ScrollViewer>
当错误发生时,我想将任何有错误的控件滚动到视图中。例如,如果用户位于列表顶部并且绑定到 PropertyX 的 TextBox 出错,那么我希望 ScrollViewer 滚动到它。
目前我从 ScrollViewer 继承并添加了以下方法。
public void ScrollErrorTextBoxIntoView()
{
var controlInError = GetFirstChildControlWithError(this);
if (controlInError == null)
{
return;
}
controlInError.BringIntoView();
}
}
public Control GetFirstChildControlWithError(DependencyObject parent)
{
if (parent == null)
{
return null;
}
Control findChildInError = null;
var children = LogicalTreeHelper.GetChildren(parent).OfType<DependencyObject>();
foreach (var child in children)
{
var childType = child as Control;
if (childType == null)
{
findChildInError = GetFirstChildControlWithError(child);
if (findChildInError != null)
{
break;
}
}
else
{
var frameworkElement = child as FrameworkElement;
// If the child is in error
if (Validation.GetHasError(frameworkElement))
{
findChildInError = (Control)child;
break;
}
}
}
return findChildInError;
}
我很难让它正常工作。在我看来,我有两个选择。
尝试让 ViewModel 执行 ScrollErrorTextBoxIntoView 方法。我不确定最好的方法是什么。我试图设置一个属性并从中采取行动,但它似乎不正确(而且它无论如何都没有用)
让控件以独立的方式进行。这将要求我的 ScrollViewer (递归地)侦听其子项并在其中任何一个处于错误状态时调用该方法。
所以我的问题是:
这两个选项中哪一个更好,您将如何实施它们?
有没有更好的方法来做到这一点?(行为等?)它必须是 MVVM。
注意。GetFirstChildControlWithError 改编自这个问题。如何按名称或类型查找 WPF 控件?