2

WPF のコンボ ボックスで、最初に開いた DataContext にぶら下がっているように見える問題が発生しました。ComboBox の DataContext を変更すると、子の PopupRoot オブジェクトが古い DataContext を参照したままになります。

最初は何か間違ったことをしていると思いましたが、それが何であるかを理解するのに苦労していたので、単純化しようとしました. 私たちのアプリケーションで見られる動作を非常に単純な形式で再現することができたので、WPF ComboBox 実装のバグのように見えます。それは少し物議を醸すように聞こえるので、stackoverflow に助けを求めようと思いました。

サンプルのコア コードは次のとおりです。

<Window x:Class="ComboBoxTest.MainWindow" 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="150" Width="525">
    <DockPanel>
        <Button Click="ReloadModel" Width="137" Height="40">Reload Model</Button>
        <ComboBox Name="ComboBox" 
            ItemsSource="{Binding AvailableOptions}" 
            SelectedItem="{Binding SelectedOption}" 
            Width="235" Height="43">
        </ComboBox>
    </DockPanel>
</Window>

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        var newModel = new ViewModel();
        ComboBox.DataContext = newModel;
    }

    private void ReloadModel(object sender, RoutedEventArgs e)
    {        
        var newModel = new ViewModel();
        ComboBox.DataContext = newModel;
    }
}

public class ViewModel : INotifyPropertyChanged
{
    public ViewModel()
        : this(new[] { "Option 1", "Option 2", "Option 3" })
    { }

    public ViewModel(IEnumerable<string> options)
    {
        _selectedOption = options.First();
        _availableOptions = new ObservableCollection<string>(options);
    }

    protected void RaisePropertyChanged(string propertyName)
    {
        var propertyChangedHandler = PropertyChanged;
        if (propertyChangedHandler != null)
        {
            propertyChangedHandler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;

    private readonly ObservableCollection<string> _availableOptions;
    public ObservableCollection<string> AvailableOptions
    {
        get
        {
            return _availableOptions;
        }
    }

    private string _selectedOption;
    public string SelectedOption
    {
        get { return _selectedOption; }
        set
        {
            if (_selectedOption == value)
            {
                return;
            }
            _selectedOption = value;
            RaisePropertyChanged("SelectedOption");
        }
    }
}

再現手順:
1) アプリケーションを実行します
2) コンボボックスを開きます (ドロップダウン オプションをレンダリングするため)
3) [モデルのリロード] ボタンをクリックします

この時点で 2 つの ViewModel オブジェクトが存在し、古い予期しないインスタンスは次のようにルート化されます: ViewModel->PopupRoot->Popup->ComboBox->MainWindow->App

これはバグですか、それとも間違っていますか?

イーモン

4

2 に答える 2