绑定的 ComboBoxItem 变量在视图更改后变为空

Bound ComboBoxItem variable turns null after view change

我有一个问题正在寻找解释。它类似于 WPF ComboBox SelectedItem Set to Null on TabControl Switch 中讨论的内容,但它涉及的绑定程度较低,因此应该对更简单的解决方案开放。我在下面描述的是我构建的一个简化案例,用于重现并尝试理解问题出现的原因。

因此,该项目基于 MVVM,主要 window 只有一个标记为“搜索”的按钮,声明如下:

<Button Margin="50,0,0,0" Width="150" Height="40" Content="Search" HorizontalAlignment="Left" Command="{Binding UpdateViewCommand}" CommandParameter="Search"/>

代码绑定UpdateView :ICommand即,定义如下:

class UpdateViewCommand : ICommand
{
    private MainViewModel viewModel;

    public UpdateViewCommand(MainViewModel viewModel)
    {
        this.viewModel = viewModel;
    }

    public event EventHandler CanExecuteChanged;

    public bool CanExecute(object parameter)
    {
        return true;
    }

    public void Execute(object parameter)
    {
        if (parameter.ToString() == "Search")
        {
            viewModel.SelectedViewModel = new SearchViewModel();
        }
    }
}

该视图与上半部分的主视图重叠,使“搜索”按钮可见,如下图所示:

该视图包含一个 ComboBox 和一个“Go”按钮,声明为:

    <ComboBox Name="SearchCriterion" Canvas.Left="128" Canvas.Top="14" Height="22" Width="257" Background="#FF66CCFF" BorderBrush="Black" SelectedIndex="0"
              SelectedItem="{Binding QueryType, Mode=OneWayToSource}">
        <ComboBoxItem FontFamily="Calibri" FontSize="14" Background="#FF66CCFF">
            Author
        </ComboBoxItem>
        <ComboBoxItem FontFamily="Calibri" FontSize="14" Background="#FF66CCFF">
            Title
        </ComboBoxItem>
    </ComboBox>
    <Button Name="SearchButton" Height="22" Content="Go" Canvas.Left="390" Canvas.Top="44" Width="45" BorderBrush="Black"
            FontFamily="Calibri" FontSize="14" Background="#FF0066FF" Command="{Binding ExecQueryCmd}" Foreground="White"/>

该按钮所做的只是通过变量 QueryType 获取 ComboBox 声明中绑定的 ComboBoxItem 值并打印它。 QueryType 声明为:

    private ComboBoxItem _queryType = new ComboBoxItem();
    public  ComboBoxItem QueryType
    {
        get { return _queryType; }
        set
        {
            Globals.mylog.Trace("In SearchViewModel.QueryType");
            _queryType = value;
            OnPropertyChanged(nameof(QueryType));
            
        }
    }

假设这是清楚的,这就是我看到的问题。我启动程序,单击“搜索”,出现 SearchView。我玩组合框,点击“开始”,一切都很好。我可以这样做几次,没问题。

现在我再次点击“搜索”。没有明显的变化(视图已经存在),但如果我单击“Go”,则会引发异常,因为变量为空(我在 Visual Studio 下 运行,因此我可以轻松检查) .请注意,如果不是在单击“搜索”后立即单击“开始”,而是单击 ComboxBox 并更改其值,则一切正常。

谁能解释一下为什么会这样,我该如何解决?

谢谢

您从未在 SearchViewModel 的构造函数中显式地为 QueryType 赋值,因此 querytype 中的值取决于 UI 来更新它。 更好的方法是让所选值来自视图模型(而不是像我在评论中提到的那样在游览视图模型中有 ui 元素)。

我改变了什么让它起作用: 在 SearchViewModel:

    /// <summary>
    /// Selected option to search by (it is now a string)
    /// </summary>
    private string _queryType;
    public  string QueryType
    {
        get { return _queryType; }
        set
        {
            Globals.mylog.Trace("In SearchViewModel.QueryType");
            _queryType = value;
            OnPropertyChanged(nameof(QueryType));
            
        }
    }

    /// <summary>
    /// List of options to search by
    /// </summary>
    public ObservableCollection<string> Queries { get; set; }

    public SearchViewModel()
    {
        Globals.mylog.Trace("In SearchViewModel");

        //Initialization ofthe list of options
        Queries = new ObservableCollection<string> { "Author", "Title" };
        //Initialization of the selected item
        this.QueryType = Queries.FirstOrDefault();
        ExecQueryCmd = new RelayCommand(ExecuteQuery, CanExecuteQuery);
    }

在搜索视图中:

<--The combobox is now bound to the list in the ViewModel(the data is stored in the viewmodels and the view is only responsible for displaying it) -->
<Canvas Width="517" Height="580" Background="#FFCCFF99">
    <ComboBox Name="SearchCriterion" Canvas.Left="128" Canvas.Top="14" Height="22" Width="257" ItemsSource="{Binding Queries}" Background="#FF66CCFF" BorderBrush="Black"
              SelectedItem="{Binding QueryType, Mode=TwoWay}">
        <ComboBox.ItemContainerStyle>
            <Style BasedOn="{StaticResource {x:Type ComboBoxItem}}" TargetType="{x:Type ComboBoxItem}">
                <Setter Property="FontFamily" Value="Calibri"/>
                <Setter Property="FontSize" Value="14"/>
                <Setter Property="Background" Value="#FF66CCFF"/>
            </Style>
        </ComboBox.ItemContainerStyle>
    </ComboBox>
    <Button Name="SearchButton" Height="22" Content="Go" Canvas.Left="390" Canvas.Top="44" Width="45" BorderBrush="Black"
            FontFamily="Calibri" FontSize="14" Background="#FF0066FF" Command="{Binding ExecQueryCmd}" Foreground="White"/>
</Canvas>