我使用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属性中的一些讨厌的代码。解决方案是,至少可以说不满意......;)所以,我希望比我更聪明的人能想出更好的解决方案!:)
答案 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