问题描述
我的问题与此问题中描述的问题相似:
DataTemplate 中的 WPF MVVM 按钮控件绑定
My problem is similar to the one described in this question:
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
,绑定到一个名为 CommandSets
的 ObservableCollection
(在 ViewModel 中).
此绑定有效(它为集合中的每个项目显示一个按钮).
It's just a ListBox
, bound to an ObservableCollection<string>
named CommandSets
(which is in the ViewModel).
This binding works (it displays a button for each item in the collection).
现在我想将按钮绑定到一个命令 (FireCommand
),该命令也在 ViewModel 中.
这是 ViewModel 的相关部分:
Now I want to bind the button to a command (FireCommand
), which is also in the ViewModel.
Here's the relevant part of the 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");
}
}
此按钮的绑定不起作用.
根据我从上面链接的 问题 中了解到的,绑定不起作用,因为:
(如果我错了,请纠正我)
The binding of this button does NOT work.
From what I've understood from the question I linked above, the binding doesn't work because:
(correct me if I'm wrong)
- 按钮在
ListBox
内部,所以它只知道"ListBox
的绑定(在本例中为ObservableCollection
),但不是主窗口的绑定 - 我正在尝试绑定到主窗口的主 ViewModel 中的命令(按钮不知道")
- The button is inside the
ListBox
, so it only "knows" the binding of theListBox
(theObservableCollection
, in this case), but not the binding of the main window - I'm trying to bind to a command in the main ViewModel of the main window (which the button doesn't "know")
命令本身绝对是正确的,因为当我将按钮放在ListBox
(参见上面的XAML示例)时,绑定有效,命令是执行.
The command itself is definitely correct, because when I put the button outside the ListBox
(see the XAML above for an example), the binding works and the command is executed.
显然,我只需要"告诉按钮绑定到表单的主 ViewModel.
但我无法找出正确的 XAML 语法.
我尝试了一些谷歌搜索后发现的方法,但没有一个对我有用:
I tried several approaches that I found after some googling, but none of them worked for me:
<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}}}" />
有人可以吗:
- 给我适当的 XAML 以将
ListBox
内的按钮绑定到表单MainViewModel
中的命令? - 指向一个链接,其中以 WPF/MVVM 初学者可以理解的方式解释了这种高级绑定内容?
我觉得我只是在复制和粘贴神秘的 XAML 咒语,到目前为止我没有任何线索(并且找不到任何好的文档)我如何自己弄清楚在哪些情况下我需要RelativeSource
或StaticResource
或其他任何东西,而不是正常"绑定.
- give me the proper XAML to bind the button inside the
ListBox
to a command in the form'sMainViewModel
? - point me to a link where this advanced binding stuff is explained in a way that a WPF/MVVM beginner can understand?
I'm feeling like I'm just copying and pasting arcane XAML incantations, and so far I don't have any clue (and can't find any good documentation) how I would figure out by myself in which cases I'd needRelativeSource
orStaticResource
or whatever instead of a "normal" binding.
推荐答案
It's:
{Binding DataContext.FireCommand,
RelativeSource={RelativeSource AncestorType=ListBox}}
除非您沿途实际更改了 DataContext
,否则无需走到根目录,但由于 ListBox
似乎绑定到主 VM 上的属性,因此应该够了.
No need to walk up to the root unless you actually change the DataContext
along the way, but as the ListBox
seems to bind to a property on the main VM this should be enough.
我唯一推荐阅读的是数据绑定概述 和 Binding
类 文档(包括其属性).
The only thing i recommend reading is the Data Binding Overview, and the Binding
class documentation (including its properties).
这里还有一个关于如何构建绑定的简短解释:一个绑定由一个 source 和一个相对于那个 Path
组成>source,默认情况下 source 是当前的 DataContext
.可以显式设置的源有:Source
、ElementName
&相对源
.设置其中任何一个都会将 DataContext
覆盖为 source.
Also here is a short explanation on how bindings are constructed: A binding consists of a source and a Path
relative to that source, by default the source is the current DataContext
. Sources that can be set explicitly are: Source
, ElementName
& RelativeSource
. Setting any of those will override the DataContext
as source.
因此,如果您使用 source 之类的 RelativeSource
并希望在该级别访问 DataContext
中的某些内容,DataContext
需要出现在Path
中.
So if you use a source like RelativeSource
and want to access something in the DataContext
on that level the DataContext
needs to appear in the Path
.
这篇关于将 DataTemplate 中的按钮绑定到表单的 ViewModel 中的命令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,WP2