2

文字列が追加または削除されるたびに文字列を検証する文字列項目の ListBox があります。

以下は私がまとめたコードですが、問題は ObservableCollection Addresses が変更されたときに ValidateAddresses が呼び出されないことです。

意図した動作は、無効な文字列が見つかった場合に、エラー メッセージを表示するツールチップと共に ListBox の周りに赤い境界線を表示することです。

この INotifyDataErrorInfo セットアップは TextBoxes に対して正常に機能するため、ここで何が間違っているのかわかりません。

ビューモデル

[CustomValidation(typeof(ItemViewModel), "ValidateAddresses")]
public ObservableCollection<string> Addresses
{
    get
    {
        return item.Addresses;
    }

    set
    {
        item.Addresses = value;
        NotifyPropertyChanged(nameof(Addresses));
    }
}

XAML

<Grid>
    <Grid.Resources>
        <Style TargetType="ListBox">
            <Setter Property="Margin" Value="5"/>
            <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
            <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>

            <Setter Property="Validation.ErrorTemplate">
                <Setter.Value>
                    <ControlTemplate x:Name="TextErrorTemplate">
                        <DockPanel LastChildFill="True">
                            <AdornedElementPlaceholder>
                                <Border BorderBrush="Red" BorderThickness="2"/>
                            </AdornedElementPlaceholder>
                            <TextBlock Foreground="Red"/>
                        </DockPanel>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>

            <Style.Triggers>
                <Trigger Property="Validation.HasError" Value="True">
                    <Setter Property="ToolTip" Value="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(Validation.Errors).CurrentItem.ErrorContent}"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </Grid.Resources>

    <ListBox ItemsSource="{Binding Path=Item.Addresses, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnNotifyDataErrors=True}" SelectedIndex="{Binding Path=SelectedAddress, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</Grid>

検証方法 (呼び出されない)

public static ValidationResult ValidateAddresses(object obj, ValidationContext context)
{
    ItemViewModel item = (ItemViewModel)context.ObjectInstance;

    if (item.Addresses.Count > 0)
    {
        foreach (string address in item.Addresses)
        {
            if (Regex.IsMatch(address, @"[^\w]"))
                return new ValidationResult($"{address} is not a valid address.", new List<string> { "Addresses" });
        }
    }

    return ValidationResult.Success;
}
4

1 に答える 1

0

私が持っていた ObservableCollection ごとにクラスコンストラクターに以下を追加することになりました。

Addresses.CollectionChanged += (sender, eventArgs) => { NotifyPropertyChanged(nameof(Addresses)); };

メモリ リークを防ぐためにイベントのサブスクライブ解除が必要な状況を調査しようとしましたが、これはこれらのケースの 1 つではないように思われるため、クリーンアップは必要ありません。

ObservableCollections はすべて Model クラスのコンストラクターで初期化されるため、null チェックは必要ありません。

返信ありがとうございます。

これが NotifyPropertyChanged のコードです。

public class ObservableObject : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
于 2016-05-25T05:27:37.467 に答える