WPF:更改后重置ComboBox

时间:2011-01-07 09:50:06

标签: wpf mvvm

我使用MVVM模式构建应用程序。在这个应用程序中,我有一个ComboBox绑定到一组项目和一个包含所选项目的属性:

<ComboBox ItemsSource="{Binding Path=Persons, Mode=OneTime}"
          SelectedValue="{Binding Path=SelectedPerson, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>

使用“指令文本”作为第一项初始化包含此ComboBox项目的集合,然后是一堆普通项目:

Persons.Add("Open Person...");
Persons.Add("Anders Andersson");
Persons.Add("Bengt Bengtsson");
Persons.Add("Carl Carlsson");
Persons.Add("Daniel Danielsson");

我想为这个ComboBox提供的行为是它最初显示指令文本(这当然很容易实现)。当用户在ComboBox中选择一个人时,应用程序会执行一些操作(打开所选人员),然后重置为指令文本。

首先想到的是,通过为所选项目提供此属性可以轻松实现:

private string _selectedPerson = "Open Person...";
public string SelectedPerson
{
    get
    {
        return _selectedPerson;
    }
    set
    {
        if (value != _selectedPerson)
        {
            OpenPerson(value);
            OnPropertyChanged("SelectedPerson");
        }
    }
}

我的想法是,当用户选择除ComboBox中的指令文本以外的任何内容时,将使用所选值调用OpenPerson(),但所选值不会存储在私有字段(_selectedPerson)中。然后我触发PropertyChanged事件,该事件将使ComboBox读取属性SelectedPerson的值并更新自身(SelectedValue)。因为_seletedPerson字段仍然是指令文本,所以ComboBox会将其自身重置为该字段。

这不起作用。

实际上,一切似乎都按照我的预期发生。使用正确的参数调用OpenPerson(),然后触发PropertyChanged事件。但是,GUI改变ComboBox显示的值的操作实际上是在所有这些之后执行的。这意味着无论我将SelectedPerson设置为什么,ComboBox都会显示在GUI中选择的项目。

有没有一种优雅的方式来解决这个问题?

实际上,我自己已经解决了这个问题。但它涉及CodeBehind中的代码,ViewModel中的两个标志以及SelectedPerson属性中的一些讨厌的代码。解决方案是,至少可以说不满意......;)所以,我希望比我更聪明的人能想出更好的解决方案!:)

2 个答案:

答案 0 :(得分:1)

您是否尝试为Combobox创建SelectionChanged处理程序并改为回复“Open Person ...”?

甚至组合框的触发器将其设置为Index = 0或其他什么?

答案 1 :(得分:0)

我刚发现这个寻找别的东西,我希望我仍然可以提供帮助。

我将命令绑定到selectionchanged事件,该命令在Viewmodel中定义,因此遵循MVVM模式(后面没有代码)。

我使用MVVM-Light框架,因此您需要包含以下内容,其中包含混合交互参考:

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:cmd="http://www.galasoft.ch/mvvmlight"

以下是我在xaml中声明它的方式:

            <ComboBox Name="idClient" Grid.Column="1" Grid.ColumnSpan="2" Grid.Row="2"
                              Style="{StaticResource FTC_DetailComboBox}"
                              ItemsSource="{Binding ClientViewSource.View}"
                              SelectedItem="{Binding client}"
                              SelectedValuePath="idClient"
                              SelectedValue="{Binding idClient, Mode=TwoWay, ValidatesOnDataErrors=True}"
                              DisplayMemberPath="chrCompany"
                              >
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="SelectionChanged">
                        <cmd:EventToCommand Command="{Binding LostFocusValidateCommand}" CommandParameter="idStatus"/>
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </ComboBox>

以下是我的viewmodel(在vb.net中)的代码。 RelayCommand是ICommand的简单实现

    Private _LostFocusValidateCommand As RelayCommand(Of String)

    Public ReadOnly Property LostFocusValidateCommand() As RelayCommand(Of String)
        Get
            If _LostFocusValidateCommand Is Nothing Then
                _LostFocusValidateCommand = New RelayCommand(Of String)(AddressOf LostFocusValidateExecute)
            End If
            Return _LostFocusValidateCommand
        End Get
    End Property

    Private Sub LostFocusValidateExecute(sParam As String)
        ''perform commands here
    End Sub