29

我的问题类似于这个问题中描述的问题:
WPF MVVM Button Control Binding in DataTemplate

这是我的 XAML:

<Window x:Class="MissileSharp.Launcher.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MissileSharp Launcher" Height="350" Width="525">
    <Grid>
        <!-- when I put the button here (outside the list), the binding works -->
        <!--<Button Content="test" Command="{Binding Path=FireCommand}" />-->
        <ListBox ItemsSource="{Binding CommandSets}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <!-- I need the button here (inside the list), and here the binding does NOT work -->
                    <Button Content="{Binding}" Command="{Binding Path=FireCommand}" />
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
</Window>

它只是一个ListBox, 绑定到一个ObservableCollection<string>命名的CommandSets(在 ViewModel 中)。
此绑定有效(它为集合中的每个项目显示一个按钮)。

现在我想将按钮绑定到命令 ( FireCommand),该命令也在 ViewModel 中。
这是 ViewModel 的相关部分:

public class MainWindowViewModel : INotifyPropertyChanged
{
    public ICommand FireCommand { get; set; }
    public ObservableCollection<string> CommandSets { get; set; }

    public MainWindowViewModel()
    {
        this.FireCommand = new RelayCommand(new Action<object>(this.FireMissile));
    }

    private void FireMissile(Object obj)
    {
        System.Windows.MessageBox.Show("fire");
    }
}

此按钮的绑定不起作用。
根据我从上面链接的问题中了解到的情况,绑定不起作用,因为:(
如果我错了,请纠正我)

  • 按钮在 内部ListBox,所以它只“知道” ListBoxObservableCollection在这种情况下是 )的绑定,而不是主窗口的绑定
  • 我正在尝试绑定到主窗口的主 ViewModel 中的命令(按钮不“知道”)

命令本身绝对正确,因为当我将按钮放在外部ListBox(请参阅上面的 XAML 示例),绑定有效并且命令被执行。

显然,我“只是”需要告诉按钮绑定到表单的主 ViewModel。
但我无法找出正确的 XAML 语法。

我尝试了几种在谷歌搜索后发现的方法,但没有一个对我有用:

<Button Content="{Binding}" Command="{Binding RelativeSource={RelativeSource Window}, Path=DataContext.FireCommand}" />

<Button Content="{Binding}" Command="{Binding Path=FireCommand, Source={StaticResource MainWindow}}" />

<Button Content="{Binding}" Command="{Binding Path=FireCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" />

有人可以请:

  1. 给我正确的 XAML 来将里面的按钮绑定ListBox到表单中的命令MainViewModel
  2. 指向一个链接,其中以 WPF/MVVM 初学者可以理解的方式解释这种高级绑定内容?
    我觉得我只是在复制和粘贴神秘的 XAML 咒语,到目前为止我没有任何线索(也找不到任何好的文档)我将如何自己弄清楚在哪些情况下我需要RelativeSourceStaticResource或其他任何东西,而不是“正常”绑定。
4

2 回答 2

75

它的:

{Binding DataContext.FireCommand,
         RelativeSource={RelativeSource AncestorType=ListBox}}

DataContext除非您实际更改路径,否则无需走到根目录,但由于ListBox似乎绑定到主 VM 上的属性,这应该足够了。

我唯一推荐阅读的是Data Binding OverviewBinding文档(包括它的属性)。


这里还有一个关于如何构造绑定的简短说明:绑定由一个和一个Path相对于该的源组成,默认情况下是当前的DataContext。可以显式设置的来源是:Source, ElementName& RelativeSource。设置其中任何一个都将覆盖DataContextas source

因此,如果您使用类似的RelativeSource并想要访问DataContext该级别中的某些内容,则DataContext需要出现在Path.

于 2012-09-10T23:00:42.253 回答
4

大多数人可能认为这不相关,但此搜索只是搜索数据模板内控件的数据绑定命令的 3 个结果中的 1 个 - 因为它与 Xamarin Forms 相关。所以,也许它现在会帮助某人。

像我一样,您可能想知道如何在 BindableLayout 中绑定命令。感谢 jesulink2514 在 Xamarin 论坛上回答这个问题,由于所有的评论,它可能被许多人忽略了。这是他的解决方案,但我包括以下链接:

<ContenPage x:Name="MainPage">
<ListView Grid.Row="1"
              ItemsSource="{Binding Customers}"
              VerticalOptions="Fill"
              x:Name="ListviewCustomer">
      <ListView.ItemTemplate>
        <DataTemplate>
      <Label Text="{Binding Property}"/>
          <Button Command="{Binding BindingContext.ItemCommand, Source={x:Reference MainPage}}" 
                         CommandParameter="{Binding .}">Click me</Button>
        </DataTemplate>
      </ListView.ItemTemplate>
    </ListView>
</ContentPage>

https://forums.xamarin.com/discussion/comment/217355/#Comment_217355

于 2019-09-18T23:23:29.443 回答