【问题标题】:How can i set the command of a button within a DataTemplate to the data context of the parent element如何将 DataTemplate 中的按钮命令设置为父元素的数据上下文
【发布时间】:2016-03-31 11:11:52
【问题描述】:

我有一个列表框,它绑定到我的视图模型中的一个可观察集合(用户控制数据上下文)。

DeviceDetector driveDetector;
public DriveSelector()
{
    InitializeComponent();

    driveDetector = DeviceDetector.Instance;
    DataContext = driveDetector;
}

这是我的列表框代码

<ListBox Style="{StaticResource ListBoxStyle}" ItemsSource="{Binding DriveCollection}">
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <Button Width="70" Style="{StaticResource DriveButtonStyle}" Command="{Binding SimpleMethod}">
                                <StackPanel>
                                    <Image Source="{Binding Image}" Style="{StaticResource DriveImageStyle}"/>
                                    <Label Content="{Binding Name}" Style="{StaticResource DriveLabelStyle}"/>
                                </StackPanel>
                            </Button>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>

我已经实现了 ICommand,当我像这样绑定到列表框外的命令时:

<Button Command="{Binding SimpleMethod}"/>

一切都很好。但是,当我尝试将命令绑定到列表框数据模板内的按钮时,我收到此错误:

System.Windows.Data 错误:40:BindingExpression 路径错误: 在“对象”“DriveInfo”上找不到“SimpleMethod”属性 (哈希码=6377350)'。绑定表达式:路径=简单方法; DataItem='DriveInfo' (HashCode=6377350);目标元素是“按钮” (名称='');目标属性是“Command”(输入“ICommand”)

我可以看到按钮的数据上下文是模型的,因此找不到方法“SimpleMethod”。有没有办法可以将命令绑定到列表框本身的数据上下文?

【问题讨论】:

  • 您可以为您的按钮编写自定义行为。这样你就可以将它绑定到你的按钮上。不知道,这个方法应该什么时候触发?

标签: c# wpf mvvm


【解决方案1】:

您可以像这样引用窗口或页面顶级 DataContext:

 <Button Content="{StaticResource Whatever}"
      DataContext="{Binding DataContext, RelativeSource={RelativeSource AncestorType=Page}}"
      CommandParameter="{Binding}"
      Command="{Binding SimpleMethod}" />

【讨论】:

  • 获得DataContext of ListBox 就足够了。此外,您在绑定中忘记了Path=SimpleCommand。在恕我直言之后,这应该是一个公认的答案。小提示:要么删除 CommandParameter(OP 似乎不需要它),要么在 before Command 之前移动它(参见 here 为什么它很重要)。
  • @Sinatr,感谢您的提示。但是我没有在我从中获取此代码的命令中使用Path,它工作正常。
  • 你是对的,出于一些奇怪的原因(对不起我之前的评论)我没有看到你正在重新分配DataContext。不要那样做。而是在Command 绑定本身中使用RelativeSourceCommand="{Binding DataContext.SimpleMethod, RelativeSource={RelativeSource FindAncestor, AncestorType=ListBox}}"
  • @Sinatr,这是什么原因?如果我重新分配上下文,那么我可以在任意数量的属性上使用它,而不必对每个属性都执行 RelativeSource,对吗?是性能/效率问题吗?
  • 好问题。对我来说,在数据模板的世界里不碰DataContext 是一个公理。也许是为了避免像this 这样的情况。不能说性能。
【解决方案2】:

SimpleMethod 的所有者是什么? DataContext 还是集合项?我怀疑DataContext。将 SimpleMethod 从 DataContext 类移动到项目类。或者像这样使用RelativeSource Bind to ItemsControl's DataContext from inside an ItemTemplate

【讨论】:

    【解决方案3】:

    我是如何解决我的问题的:

    首先,我创建了我的视图模型的静态资源。然后将其绑定到我在 xaml 中的数据上下文

    <UserControl.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="pack://application:,,,/Styles;component/Resources.xaml" />
            </ResourceDictionary.MergedDictionaries>
            <vm:DeviceSelectorViewModel x:Key="myViewModel" x:Name="myVM" />
        </ResourceDictionary>
    </UserControl.Resources>
    
    <UserControl.DataContext>
        <StaticResourceExtension ResourceKey="myViewModel"/>
    </UserControl.DataContext>
    

    这允许我将命令的源更改为(静态资源)视图模型,如下所示:

    <Button Width="70" Style="{StaticResource DriveButtonStyle}" Command="{Binding SimpleCommand, Source={StaticResource myViewModel}}" >
    

    感谢您的回复!

    【讨论】:

      猜你喜欢
      • 2016-04-30
      • 2011-01-26
      • 1970-01-01
      • 2016-09-30
      • 1970-01-01
      • 2017-03-15
      • 1970-01-01
      • 2020-05-28
      • 1970-01-01
      相关资源
      最近更新 更多