【问题标题】:MVVM DataBindingMVVM 数据绑定
【发布时间】:2013-01-07 14:14:29
【问题描述】:

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

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'."}

我们知道 ViewModel 被适当地设置为 View 窗口的 DataContext。我究竟做错了什么?

【问题讨论】:

  • 嘿 Sammarcow... 你过得怎么样?最后成功了吗?

标签: .net wpf user-interface data-binding mvvm


【解决方案1】:

你正在使用;

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

这实际上是一个事件。

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

假设您的窗口具有 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

文本绑定版本:

当然,如果您只对他们选择的文本值感兴趣,理论上您可以将 ComboBox 文本属性绑定到 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}" />

视图模型;

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

注意多余的@符号。

正如我上面提到的,这假设您的 Window 在此处设置了 DataContext。如果没有,则从上面的 Bindings 中删除“DataContext。”!

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

希望这会有所帮助!

【讨论】:

  • 绑定到 SelectedIndex 需要对 ViewModel 中的 XML 数据源的另一个引用来确定与 DisplayMEmeber 关联的值,不是吗?否则我只会知道 SelectedIndex,因为 ComboBox 是从外部数据源填充的。
  • 嗯,我不确定我做错了什么,但&lt;ComboBox x:Name="cbConnection" ItemsSource="{Binding Source={StaticResource XmlConnectionList}, XPath=//ComboItem}" DisplayMemberPath="Key" SelectedValuePath="Value" SelectedItem="{Binding Path=DataContext.ConnectionString}" /&gt; 似乎没有在我的 ViewModel 中触发 getter 或 setter 属性 ConnectionString。
  • 我已经用一些示例代码编辑了我的原始答案...它在 VB 中,但如果需要,您应该可以很容易地转换为 C# ;-)
  • 我可能是错的,但该绑定不是解析为 DataContext.DataContext.ConnectionString 的属性路径吗?试试 SelectedItem="{Binding Path=ConnectionString}"
  • 与问题没有直接关系,但您的评论“这实际上是一个事件”。提示我检查我的 XAML,我试图将布尔值绑定到 CheckBox 的“已检查”属性。 “检查”确实是一个事件!将其绑定到 IsChecked ,一切都很好。
【解决方案2】:

您必须为组合框选择更改事件使用事件触发器 你应该试试下面提到的代码

<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" 

【讨论】:

  • 我没有对此进行测试,但接受的答案似乎确实有效地达到了相同的结果。
猜你喜欢
  • 1970-01-01
  • 2015-07-15
  • 2015-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-07-17
  • 2012-10-29
相关资源
最近更新 更多