開発中のアプリケーション全体で再利用されるUserControlがあります。 MVVMLightに基づくフレームワークを使用しています。MVVMとDataAnnotationsを使用したWPF、UserControlの検証エラー
簡潔にするため、ユーザーコントロールには1つのテキストボックスのみが含まれており、 "Quantity"という1つの依存プロパティが公開されています。ユーザーコントロールのテキストボックスは、依存プロパティ "Quantity"にデータバインドされています。
ビューでユーザーコントロールを使用すると、usercontrolの "Quantity"依存プロパティは、ViewModelのプロパティにバインドされます。 (このViewModelは、MVVMLight ViewModelLocatorによるビューのデータコンテキストです)。
これはすべて素晴らしいです!バインディングは機能し、プロパティは期待どおりに設定されます。バリデーションに至るまで、すべてがうまくいきます。
私たちは、DataAnnotationsを使ってViewModelプロパティを飾っています。 ViewModelには、INotifyDataErrorInfoのカスタム実装が含まれています。ほとんどの入力コントロールにカスタムスタイルを実装して、コントロールの周りに赤い境界線を表示し、コントロールの隣にメッセージを表示して、検証エラーメッセージを表示しました。これはすべて、通常のケースではうまくいきます(たとえば、ビューモデルのプロパティにバインドされたビュー上のテキストボックス)。
このユーザーコントロールを使用して同じアプローチを試みると、最終的にユーザーコントロール全体が赤い境界線になり、実際のテキストボックスにエラーが表示されなくなります。エラーがあるという事実はUIに反映されているように見えますが、私が望むコントロールには反映されていません。
私はこの問題の解決策についてはstackoverflowを検索しましたが、解決策がない質問はありません。
私の最初の推測は、実際のテキストボックスは、ビューモデルのプロパティではなく、依存プロパティ自体に直接バインドされているため、生成されたエラーを適切に通知されていないことです。ビューコントロールで生成されたエラーを、ユーザーコントロールからテキストボックスに伝える方法はありますか?
助けてもらえますか?ありがとうございます。
ここにUserControl xamlがあります。
<UserControl x:Class="SampleProject.UserControls.SampleControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d" x:Name="sampleControl"
d:DesignHeight="300" d:DesignWidth="300">
<Grid x:Name="LayoutRoot" DataContext="{Binding ElementName=sampleControl}">
<TextBox Text="{Binding Path=Quantity, ValidatesOnDataErrors=True}" Width="100" Height="30" />
</Grid>
</UserControl>
背後にあるUserControlコード。
public partial class SampleControl : UserControl
{
public SampleControl()
{
InitializeComponent();
}
public static readonly DependencyProperty QuantityProperty =
DependencyProperty.Register("Quantity", typeof(int?), typeof(SampleControl),
new FrameworkPropertyMetadata{DefaultValue=null, BindsTwoWayByDefault = true});
public int? Quantity
{
get { return (int?)GetValue(QuantityProperty); }
set { SetValue(QuantityProperty, value); }
}
}
ビューに使用されます。
<userControls:SampleControl Grid.Row="1" Quantity="{Binding Path=Quantity, ValidatesOnDataErrors=True}" Height="60" Width="300"/>
ViewModelプロパティ。
[Required(ErrorMessage = "Is Required")]
[Range(5, 10, ErrorMessage = "Must be greater than 5")]
public int? Quantity
{
get { return _quantity; }
set { Set(() => Quantity, ref _quantity, value); }
}
private int? _quantity;
(*注、セッターでの設定方法は、バッキングプロパティを設定し、それのためにPropertyChangedイベントを発生させ、ベースのviewmodelでちょうどヘルパーメソッドです。)
コードが機能しているとき、エラーメッセージは同じTextBoxに表示されますか? – Tico
はい。そのテキストボックスがビュー自体にあり、ViewModelのQuantityプロパティに直接バインドされている場合、検証エラーがテキストボックスに表示されます。しかし、テキストボックスがユーザーコントロール内にあり、バインディングがユーザーコントロールの依存関係プロパティを通過すると、検証エラーは失われます。 – thornhill
ブレークポイントを置いても? – Tico