【问题标题】:WPF MVVM - repeated combobox, pass selectedItem as parameterWPF MVVM - 重复组合框,将 selectedItem 作为参数传递
【发布时间】:2024-04-12 22:55:02
【问题描述】:

仍然从 web/MVC 的背景中掌握 WPF。我已经实现了一些在 UI 场景中很常见的东西,一个重复的项目列表以及一些控件,以允许用户对这些项目执行操作(我省略了一些绑定,因为它们是长的 relativeSource 指令,它们是与问题无关):

<ItemsControl ItemsSource="{Binding Counts}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <ComboBox ItemsSource="{}" DisplayMemberPath="Description"></ComboBox>
                <Button Command="{}" Content="Add></Button>
                <TextBlock VerticalAlignment="Center">
                    <Run Text="{Binding Path=Date, StringFormat=dd/MM/yyyy}"></Run>
                    <Run Text=" - "></Run>
                    <Run Text="{Binding Name}"></Run>
                </TextBlock>
            </StackPanel>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

如您所见,ComboBox 没有实现 SelectedValue 或 SelectedValuePath - 它不能真正绑定到 ViewModel 属性,因为它对 Counts 中的每个项目都重复。所以目前它只包含一个可能值的列表。

Button 命令绑定回 ViewModel 上的命令。但是,为了在按钮按下时执行任何操作,我需要将参数传递到命令中 - 即 Button 绑定到的项目的 ID 以及用户在与此按钮配对的特定 ComboBox 中选择的任何内容。

ID 很简单——我可以为此绑定一个 CommandParameter。但是如何将选定的 ComboBox ID 传递给函数,以及如何确保它是配对 ComboBox 的 ID?

编辑:进一步的研究表明,虽然传递一个 CommandParameter 很简单,但传递两个却不是。我看到了涉及转换器的答案,但在这种情况下,我的两个参数来自不同的来源,所以我真的不能这样做。对于如何通过两者的帮助也将不胜感激。

【问题讨论】:

  • 您尝试过 ElementName 绑定吗?
  • 没有。我认为它会失败,因为 ComboBox 在 ItemsControl 中,因此每个 ComboBox 将具有相同的 Name 属性。不是这样吗?
  • 有一个命名范围的概念,名称必须是唯一的,只有在它的命名范围内。
  • 你说的很对。它确实有效。现在我只需要弄清楚如何通过两者:) 谢谢。

标签: c# wpf xaml mvvm combobox


【解决方案1】:

这是您可以传递来自任意来源的多个值的方法 - 您可以采用与用于补偿 Silverlight 中缺少的 MultiBinding 的方法相同的方法 - 中继。这个想法很简单——创建一个合成的FrameworkElement(这里是FE)作为绑定外观,我会选择一个轻量级的——例如TextBlock

使用MultiBindingConverter 将其Tag 属性绑定到您的多个位置,各个腿将绑定到各个元素名称。转换器将简单地打包来自多个来源的值并将其返回 - 它可以是逗号分隔的字符串,也可以是由您决定的对象。转换器的返回显然会保存在你的外观 FETag 属性中。

最终使用ElementName 作为源和Tag 作为路径绑定到外观FE

【讨论】:

  • 感谢您的帮助 - 非常感谢。我尝试了这个,直接多重绑定到 CommandParameter,以及您使用标签作为外观的建议。然而,在这两种情况下,虽然转换器似乎返回了正确的 object[] 值,但当它们到达命令函数时,它只是一个空数组。编辑 - 啊哈,这里的解决方案:*.com/questions/13713814/…
  • 可能是因为扭曲的绑定等等 - 在 SL 中使用 countelss 次数应该可以正常工作
【解决方案2】:

一种方法是让组合框双向绑定到counts 集合中对象类的属性。然后,您在组合中所做的选择将直接更改相应的对象,然后您无需在单击按钮时手动检测/进行这些更改。

就目前而言,counts 集合的类型可能不支持,因此您可以创建一个添加这些额外属性的类,并在您的集合中使用这些属性。然后,您的按钮将对counts 集合进行操作,以根据需要创建/更改数据。

【讨论】:

  • 问题是集合项甚至没有用虚拟机包装,它们通常是模型的集合,为模型实现 INotifyPropertyChanged 听起来并不是一个好主意。
  • 不确定我是否关注。我使用了类似的方法,因此我有一些模型类的 ObservableCollection。然后将该集合设置为某个控件(例如 DataGrid)的 ItemSource,然后将控件绑定到该模型类的属性。因此,网格的每一列、每一行都有某种方式来改变特定模型对象的值。按钮本身绑定到 VM 上的命令(集合是其属性),它允许您根据需要保存或重新调整集合。