【问题标题】:Binding Command in DataTemplateDataTemplate 中的绑定命令
【发布时间】:2017-01-31 06:01:14
【问题描述】:

我用 MVVM 模式制作了 UWP 应用程序(我是这么认为的 :)) 我的应用程序有列表框的数据模板。 View.xaml 中的列表框:

<ListBox x:Name="lbMySongs" ItemsSource="{Binding Path=MySongs}" ItemTemplate="{StaticResource lbSongsTemplate}" Grid.Row="1">
        <ListBox.ItemContainerStyle>
            <Style TargetType="ListBoxItem">
                <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
            </Style>
        </ListBox.ItemContainerStyle>
</ListBox/>

日期模板资源:

       <DataTemplate x:Key="lbSongsTemplate">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="auto"/>
                <ColumnDefinition Width="auto"/>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="auto"/>
                <ColumnDefinition Width="auto"/>
            </Grid.ColumnDefinitions>
            <TextBlock Text="{Binding Path=Artist}" Grid.Column="0"/>
            <TextBlock Text=" - " Grid.Column="1"/>
            <TextBlock Text="{Binding Path=Title}" Grid.Column="2"/>
            //Here i bind command, but it's not binding cos ItemsSource have no command. ViewModel have this command.
            <Button Command="{Binding Path=DownloadCommand}" Content="{Binding Path=Query}"/>
            <TextBlock Text="{Binding Duration}" Grid.Column="5" HorizontalAlignment="Right"/>
        </Grid>
       </DataTemplate>

需要为此按钮设置DataContext。 我在 ViewModel 中的命令。示例:

class ViewModel
{
    ...
    public RelayCommand DownloadCommand { get; set; }
    public ObservableCollection<SomeClass> MySongs { get; set; }
    ...
}

我的问题:DataTemplate 有 ItemsSource = ViewModel.MySongs。但是“DownloadCommand”在 ViewModel 中。 我在 DataTemplate 中为我的按钮集绑定到 DownloadCommand 输入了什么?

【问题讨论】:

  • 选择按钮->点击键盘上的F4你会看到属性->搜索命令->点击文本框后的小灰色按钮,选择创建绑定->从绑定窗口中选择你的DownloadCommand -> 瞧

标签: c# wpf xaml mvvm uwp


【解决方案1】:

尝试使用:

<Button Command="{Binding Path=DataContext.DownloadCommand, ElementName=lbMySongs}"
        CommandParameter="{Binding}"
        Content="{Binding Path=Query}"/>

然后改变

public RelayCommand DownloadCommand { get; set; }

public RelayCommand<SomeClass> DownloadCommand { get; set; }
...
DownloadCommand = new RelayCommand<SomeClass>(DownloadExecute);
...
private voir DownloadExecute(SomeClass item)
{
    ...
}

【讨论】:

    【解决方案2】:

    使用RelativeSource 绑定表示您要绑定到ListBox.DataContext.DownloadCommand

    <Button Command="{Binding Path=DataContext.DownloadCommand, 
                              RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}" 
            Content="{Binding Path=Query}"/>
    

    通常的做法是将CommandParameter 绑定到项目以了解命令在哪个项目上执行:

    <Button Command="{Binding Path=DataContext.DownloadCommand, 
                              RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}" 
            CommandParameter="{Binding }"
            Content="{Binding Path=Query}" />
    

    您也可以使用ElementName 绑定,但是您必须为您的ListBox 指定一个名称以在您的DataTemplate 中指定,而且我个人不喜欢在我的DataTemplates 中硬编码ElementName。如果您更改某些名称或想在另一个 ListBox 中使用 DataTemplate,查找和修复会很烦人。

    【讨论】:

    • 这在 UWP 中不起作用,因为 FindAncestor 不支持 RelativeSource 绑定
    • @ndonohoe Ahhhh 我在 UWP 中忘记了这一点。在 Google 上快速搜索“UWP FindAncestor”会找到 this StackOverflow post,其中包含使用 DependencyProperty 来提供这种行为的建议。我个人会尝试设置类似这样的自定义功能来替换 FindAncestor 功能而不是使用 ElementName,尽管如果失败,使用 ElementName 将始终有效。 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-11-22
    • 1970-01-01
    • 2021-10-25
    • 1970-01-01
    • 2020-05-28
    • 2015-07-29
    • 2013-10-23
    相关资源
    最近更新 更多