入力された値が既に存在する場合にエラーを返す検証ノードを作成する必要があります。名前を設定できる項目の GUI があります。名前を一意にする必要があります。
したがって、検証ごとに、次の 2 つのパラメーターが必要です。
- すべてのアイテムのすべての名前のリスト、または名前が存在することを知らせる述語
- 上記の検証から除外する現在のアイテム名 (名前を同じ値に変更してもエラーにはなりません)
データ コンテキストは次のようになります (説明のためのインターフェイスのみ)。
class AppMainContext
{
public IEnumerable<string> ItemNames {get;}
public Item SelectedItem {get;}
}
class Item
{
public string Name {get;}
}
WPF のフィールドは次のようになり、その親は `{SelectedItem} にバインドされます。
<DockPanel DockPanel.Dock="Top">
<Label Content="Name: "/>
<TextBox DockPanel.Dock="Top">
<TextBox.Text>
<Binding Path="Name" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<vmvalidation:UniqueNameRule />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
</DockPanel>
バリデータは次のようになります。
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Windows.Controls;
namespace MyApp.Validation
{
public class UniqueNameRule : ValidationRule
{
public IEnumerable<string> ExistingNames { get; set; }
public string MyName { get; set; }
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
if(value is string newValue)
{
// name changed
if(!value.Equals(MyName))
{
if(ExistingNames.Contains(newValue))
{
return new ValidationResult(false, "Name already exists!");
}
}
return new ValidationResult(true, null);
}
else
{
return new ValidationResult(false, "Invalid value type. Is this validator valid for the given field?");
}
}
}
}
少なくとも現在の名前をバリデーターにバインドしようとしました。テキスト ボックスは現在のアイテム データ コンテキストに既に存在するため、正しいバインドは次のようになります。
<Binding.ValidationRules>
<vmvalidation:UniqueNameRule MyName="{Binding Name}" />
</Binding.ValidationRules>
これによりエラーが発生することを除いて:
メンバー
MyName
が認識されていないか、アクセスできません。
すべての項目のリストは Windows データ コンテキストにあり、 からアクセスできますItemNames
。次のようにアクセスできると思います。
{Binding Path=DataContext.ItemNames, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}
以下の回答を使用して正しいバインディングを試みましたが、エラーが発生しました。
タイプ の 'MyName' プロパティに 'Binding' を設定することはできません
MyProject_Validation_UniqueNameRule_9_468654
。「Binding」は、DependencyObject の DependencyProperty でのみ設定できます。
バインディングはまったくサポートされていないようです。
では、検証ルールがこれらの変数の両方にアクセスできるようにするには、どうすればこれをまとめることができるでしょうか?