【问题标题】:WPF MVVM: How to enable/disable buttons in ListBox if I'm using a DataTemplateWPF MVVM:如果我使用 DataTemplate,如何在 ListBox 中启用/禁用按钮
【发布时间】:2012-12-12 07:52:48
【问题描述】:

我有一个带有 ListBox 的 WPF/MVVM 应用程序,它通过 DataTemplate 显示数据。按下按钮时,我设法更改了ListBox 中的选定项目,因此CommandParameter 链接到ListBoxSelectedItem,但我无法以相同的方式正确启用/禁用按钮.例如,如果我有 2 个项目并且按钮应该在一个中启用而在另一个中禁用,当我选择一个元素时,两个按钮的状态相同,当我选择另一个项目时它们都改变状态。

我正在使用许多 MVVM 框架中使用的RelayCommand

这是我的 XAML(删除了“不感兴趣”的部分):

<UserControl.Resources>

    <DataTemplate x:Key="ItemTemplate">
            <Grid>
                <Button Content="Something" Name="EnabledDisabledButton" Click="Button_Click"
                            Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Path=DataContext.SomeCommand}"
                            CommandParameter="{Binding RelativeSource={RelativeSource AncestorType={x:Type ListBox}}, Path=SelectedItem}"/>
            </Grid>
    </DataTemplate>


    <Style TargetType="{x:Type ListBoxItem}" x:Key="ContainerStyle">
        <Setter Property="ContentTemplate" Value="{StaticResource ItemTemplate}" />
    </Style>

</UserControl.Resources>

   <ListBox x:Name="myListBox" ItemsSource="{Binding ElementList}"
             IsSynchronizedWithCurrentItem="True" ItemContainerStyle="{StaticResource ContainerStyle}"/>

我尝试将SelectedItem作为参数传递给RelayCommandCanExecute方法,结果还是和之前一样。

有没有办法将按钮“居住”在其中的实际ListBoxItem作为参数传递给命令,因此每个都将由CanExecute方法单独处理?如果我得到了它会起作用吗? (现在我正在处理Click 事件以在执行命令之前在列表中选择正确的项目)。

在我的CanExecute 方法中,我正在评估SelectedItem 的某些属性,以便启用/禁用相应的按钮。另一种方法是评估所有元素的此属性,但我想不出在ViewModel 内执行此操作的方法,然后将结果传达给视图(如果在使用DataTemplate 时甚至可以项目)。

感谢您的意见,问候!

【问题讨论】:

  • 什么?我不明白。您需要选择的项目做什么?另外,为什么按钮有一个点击处理程序?为什么不只是CommandParameter="{Binding}"
  • 你使用了奇怪而困难的绑定。我宁愿将SomeCommand 属性添加到每个项目。此外,您根本不需要命令参数。如果每个项目都是一个视图模型,它们可以引用父视图模型并调用它的方法。
  • @HighCore 该按钮有一个 Click 处理程序,因为列表框项内的按钮处理单击事件,因此当您单击未选中元素上的按钮时,列表会在执行其之前将焦点更改为该元素命令。关于绑定,你完全正确,我只是陷入了自己的混乱。
  • @vorrtex,我会考虑你的建议,确实有可能解决这个问题(即使我正在使用虚拟机处理整个项目列表,我也不使用虚拟机包装它们中的每一个)。谢谢你们的意见。
  • @HighCore 请发表您的评论作为我批准它的答案,当我按照您的建议更改 CommandParameter 绑定时,我必须通过将其传递给 RelayCommand 并检查其中一个来使其工作对象的属性。非常感谢你,你一直很有帮助。

标签: wpf mvvm listbox command datatemplate


【解决方案1】:

将我的评论转化为答案:

为什么不只是CommandParameter="{Binding}"

【讨论】:

    【解决方案2】:

    您在问题中提到了“MVVM”,但您似乎充分利用了 MVVM 方式。

    我根本不会在样式中有 Button_Click 事件。那是因为它实际上是一种样式,根据定义可以将其更改为不具有相同事件的另一种样式,如果您将来选择使用基于样式的应用程序,这将再次使应用程序停止工作. 我使用的规则是风格就是风格。样式与应用程序的 UI 和“外观”有关。 功能应该与 UI 分开。程序员可以定义命令,设计者可以决定用户如何以最佳方式使用它。

    这正是代码与 MVVM 模式分离的地方。 将“外观”和用户行为与应用程序的逻辑分开。 就像...如果命令从按钮、菜单、数据上下文或击键触发,对模型来说应该无关紧要。

    如果这个特殊问题由我处理,我会通过拥有一个 HOLDER 类来解决它。 这是一个类(实现 INotifyPropertyChanged 的​​ DependencyObject),它包含一个 ICommand 属性以及将在 ListBox 的各个行中显示的“行”。

    ICommand 属性将绑定到 Button,将行(类)本身作为调用的 CommandParameter。 然后将在 ListBox 上的 ItemTemplate 中使用实际行,并绑定到不同的元素(带有或不带有转换器的属性)以提供所需的显示。

    我希望我解释得足够好... 如果您想了解我的解决方案替代方案的更多详细信息,请随时询问更多信息。

    【讨论】:

    • 感谢您的意见,但我已经根据 HighCore 评论解决了它。关于点击事件,我发现这是一个解决方案,当我点击项目的按钮时,让 listboxitem 被选中,因为否则按钮处理点击并且元素永远不会被选中,导致其他问题(至少在我当前架构)。
    猜你喜欢
    • 2021-05-18
    • 2011-03-29
    • 2019-02-01
    • 2011-12-16
    • 2013-07-03
    • 2019-06-16
    • 1970-01-01
    • 2013-11-23
    相关资源
    最近更新 更多