itemssource と selecteditem にバインドされたコンボボックスで奇妙なエラーをデバッグしようとしています。それは私を夢中にさせています。
コンボボックスが存在する選択されたタブ項目を変更すると、問題が発生します。(実際には、ComboBox の DataContext を変更する場合のみです)。SelectedItem バインディングには、値が null の場合にエラーを与えるカスタム検証ルールがあります。
問題は、wpf がタブ項目(DataContext) を切り替えるときにカスタム ルールを呼び出し、selecteditem-source が決して null ではないにもかかわらず、null の値を検証しようとすることです。これは問題です。
これは、同じエラーを示す単純化されたケースです。
NotNullValidationRule.Validateにブレークポイントを設定し、どのビュー モデル インスタンスにも存在しない場合でも、WPF が SelectedItem を null として検証しようとする方法を確認します。
アップデート
さらに実験を重ねた結果、TabControl は実際には無関係であることがわかりました。単純な ComboBox と DataContext を切り替えるボタンを使用しても、まったく同じ問題が発生します。コード例を新しいバージョンに置き換えています。
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
namespace ComboBoxValidationBugTest
{
public partial class MainWindow : Window
{
private Test t1, t2;
public MainWindow()
{
InitializeComponent();
t1 = new Test();
t1.Items.Add("A");
t1.Items.Add("B");
t1.Items.Add("C");
t1.SelectedItem = "A";
t2 = new Test();
t2.Items.Add("B");
t2.Items.Add("C");
t2.Items.Add("D");
t2.SelectedItem = "B";
ComboBox1.DataContext = t1;
}
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
ComboBox1.DataContext = ComboBox1.DataContext == t1 ? t2 : t1;
}
}
public class Test : INotifyPropertyChanged
{
private string _selectedItem;
private ObservableCollection<string> _items = new ObservableCollection<string>();
public ObservableCollection<string> Items
{
get
{
return _items;
}
}
public string SelectedItem
{
get
{
return _selectedItem;
}
set
{
_selectedItem = value;
OnPropertyChanged("SelectedItem");
}
}
public override string ToString()
{
return _selectedItem;
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
public class NotNullValidationRule : ValidationRule
{
public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
{
if (value == null)
{
return new ValidationResult(false, "Value was null");
}
return new ValidationResult(true, null);
}
}
}
そしてXAML:
<Window x:Class="ComboBoxValidationBugTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:comboBoxValidationBugTest="clr-namespace:ComboBoxValidationBugTest"
Title="MainWindow" Height="350" Width="525">
<Grid>
<DockPanel>
<Button Content="Toggle DataContext" DockPanel.Dock="Top" Click="ButtonBase_OnClick" />
<ComboBox ItemsSource="{Binding Items}" VerticalAlignment="Top" x:Name="ComboBox1">
<ComboBox.SelectedItem>
<Binding Path="SelectedItem">
<Binding.ValidationRules>
<comboBoxValidationBugTest:NotNullValidationRule />
</Binding.ValidationRules>
</Binding>
</ComboBox.SelectedItem>
</ComboBox>
</DockPanel>
</Grid>
</Window>