2013-01-23 156 views
6

我有一个ComboBox,在应用程序启动时将DataContext定义为适当的ViewModel。我想要从XML文件中获取项目,但将用户选择绑定到ViewModel,最终绑定到模型。MVVM数据绑定

XAML:

<ComboBox x:Name="cbConnection" 
      ItemsSource="{Binding Source={StaticResource XmlConnectionList}, XPath=//ComboItem}" 
      DisplayMemberPath="Key" 
      SelectedValuePath="Value" 
      SelectionChanged="{Binding Path=DataContext.cbConnection_SelectionChanged}" 
      /> 

,但我得到以下异常在运行时:

{"Unable to cast object of type 'System.Reflection.RuntimeEventInfo' to type 'System.Reflection.MethodInfo'."}

我们知道视图模型被适当地设置为查看窗口的DataContext的。我究竟做错了什么?

+0

添加引用嘿Sammarcow ...如何做你继续?它到底有效吗? – PGallagher

回答

13

您正在使用;

SelectionChanged="{Binding Path=DataContext.cbConnection_SelectionChanged}" 

这实际上是一个事件。

您应该将您的ViewModel中的公共属性(可能实现INotifyPropertyChanged)绑定到SelectedItem属性以管理Selection中的更改。

假设你的窗口有DataContext的,而不是组合框本身...

的SelectedItem绑定版本:

所以,你的XAML会是这样;

<ComboBox x:Name="cbConnection" 
      ItemsSource="{Binding Source={StaticResource XmlConnectionList}, XPath=//ComboItem}" 
      DisplayMemberPath="Key" 
      SelectedValuePath="Value" 
      SelectedItem="{Binding Path=DataContext.cbConnectionSelectedItem}" 
/> 

而在你的ViewModel;

Private _cbConnectionSelectedItem As XmlElement 

Public Property cbConnectionSelectedItem As XmlElement 
    Get 
     Return _cbConnectionSelectedItem 
    End Get 
    Set(value As XmlElement) 
     If value.Equals(_cbConnectionSelectedItem) = False Then 
      _cbConnectionSelectedItem = value 
      OnPropertyChanged("cbConnectionSelectedItem") 
      End If 
    End Set 
End Property 

文字效力之版本:

当然,如果您的所有感兴趣的是他们选择了什么样的文本值,理论上你可以只绑定组合框文本属性的公共字符串ViewModel中的属性;

然后,您的XAML将会;

<ComboBox x:Name="cbConnection" 
       ItemsSource="{Binding Source={StaticResource XmlConnectionList}, XPath=//ComboItem}" 
       DisplayMemberPath="Key" 
       SelectedValuePath="Value" 
       Text="{Binding Path=DataContext.cbConnectionText}" 
    /> 

而你的ViewModel;

Private _cbConnectionText As String 

Public Property cbConnectionText As String 
    Get 
     Return _cbConnectionText 
    End Get 
    Set(value As String) 
     If value.Equals(_cbConnectionText) = False Then 
      _cbConnectionText = value 
      OnPropertyChanged("cbConnectionText") 
      End If 
    End Set 
End Property 

的SelectedValue绑定版本:

如果要显示的重点,但想从键/值对的值,那么你应该绑定到的SelectedValue;

XAML;

<ComboBox x:Name="cbConnection" 
    ItemsSource="{Binding Source={StaticResource XmlConnectionList}, XPath=//ComboItem}" 
    DisplayMemberPath="@Key" 
    SelectedValuePath="@Value" 
    SelectedValue="{Binding Path=DataContext.cbConnectionValue}" /> 

ViewModel;

Private _cbConnectionValue As String 

Public Property cbConnectionValue As String 
    Get 
     Return _cbConnectionValue 
    End Get 
    Set(value As String) 
     If value.Equals(_cbConnectionText) = False Then 
      _cbConnectionValue = value 
      OnPropertyChanged("cbConnectionValue") 
      End If 
    End Set 
End Property 

请注意额外的@符号。

正如我上面提到的,这假定你的窗口在这里设置了DataContext。如果没有,那么从上面的Bindings中删除“DataContext。”的!

我假设您目前在您的ComboBox中看到列出的项目?

希望这会有所帮助!

+0

绑定到SelectedIndex需要对ViewModel中的XML数据源进行另一次引用,以确定与DisplayMEmeber关联的值,不是吗?否则,我只会知道SelectedIndex,因为ComboBox是从外部数据源填充的。 – sammarcow

+0

对不起,我很快注意到我的意思是选定的项目... – PGallagher

+0

嗯,我不知道我在做什么错误,但是'似乎不火的getter和setter属性内的ConnectionString我的ViewModel。 – sammarcow

7

你必须使用事件触发的组合框选择改变事件 你应该尝试以下提到的代码

<ComboBox Margin="192,5,5,5" DisplayMemberPath="AttachmentName" ItemsSource="{Binding AttachementList, Mode=TwoWay}" Style="{StaticResource BasicComboBoxStyle}" BorderThickness="2" BorderBrush="DarkGray" 
          Name="cmb_AttchDetails" Width="287" Height="25" SelectedItem="{Binding Defaultrequiredattachment, Mode=TwoWay}"> 
        <l:Interaction.Triggers> 
         <l:EventTrigger EventName="SelectionChanged"> 
          <l:InvokeCommandAction Command="{Binding DataContext.AttachmentNameCommand,Mode=TwoWay,RelativeSource={RelativeSource AncestorType=controls:ChildWindow}}" CommandParameter="{Binding ElementName=cmb_AttchDetails,Path=SelectedItem}" /> 
         </l:EventTrigger> 
        </l:Interaction.Triggers> 
       </ComboBox> 

这些,你必须像

xmlns:l="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" 
+0

我没有测试过这个,但接受的答案似乎有效地达到了相同的结果。 – sammarcow