私は、最も基本的なレベルで、多くの TextBoxes を含む StackPanel (Orientation=Vertical) を持つ ScrollViewer であるコントロールを持っています。
<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;
}
うまく動かせなくて困っています。私の見方では、2 つの選択肢があります。
ScrollErrorTextBoxIntoView メソッドを実行する ViewModel の取得を試みます。それを行う最善の方法が何であるかはわかりません。私はプロパティを設定してそれから行動しようとしていましたが、それは正しくないように見えました (とにかくうまくいきませんでした)
コントロールに自己完結型の方法で実行させます。これには、ScrollViewer がその子を (再帰的に) リッスンし、それらのいずれかがエラー状態にある場合はメソッドを呼び出す必要があります。
だから私の質問は:
これら 2 つのオプションのどちらが優れていて、どのように実装しますか?
これを行うより良い方法はありますか?(動作など?) MVVM である必要があります。
注意。GetFirstChildControlWithError は、この質問から適応されました。名前またはタイプで WPF コントロールを見つけるにはどうすればよいですか?