首页 > 解决方案 > 视图更改后绑定的 ComboBoxItem 变量变为空

问题描述

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

因此,该项目是基于 MVVM 的,主窗口只有一个标有“搜索”的按钮,声明如下:

<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 并在之前更改其值,则一切正常。

谁能解释我为什么会发生这种情况,以及我该如何解决?

谢谢

标签: c#wpfdata-bindingcombobox

解决方案


您从未在 QueryType 的构造函数中显式地为 QueryType 赋值SearchViewModel,因此 querytype 中的值取决于 UI 来更新它。一个更好的方法是让 selectedvalue 来自视图模型(并且没有我在评论中提到的游览视图模型中的 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>

推荐阅读