C# 将 DataTemplate 中的按钮绑定到表单的 ViewModel 中的命令
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12360560/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Bind button in DataTemplate to command in the form's ViewModel
提问by Christian Specht
My problem is similar to the one described in this question:
WPF MVVM Button Control Binding in DataTemplate
我的问题类似于这个问题中描述的问题:
WPF MVVM Button Control Binding in DataTemplate
Here is my XAML:
这是我的 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>
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).
它只是一个ListBox, 绑定到一个ObservableCollection<string>命名的CommandSets(在 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:
现在我想将按钮绑定到命令 ( 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");
}
}
The binding of this button does NOT work.
From what I've understood from the questionI linked above, the binding doesn't work because:
(correct me if I'm wrong)
此按钮的绑定不起作用。
从我从上面链接的问题中了解到,绑定不起作用,因为:(
如果我错了,请纠正我)
- 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,所以它只“知道”ListBox(ObservableCollection在本例中为 )的绑定,而不知道主窗口的绑定 - 我正在尝试绑定到主窗口的主 ViewModel 中的命令(按钮不“知道”)
The command itself is definitely correct, because when I put the button outsidethe ListBox(see the XAML above for an example), the binding works and the command is executed.
命令本身是绝对正确的,因为当我把按钮之外的ListBox(见上面的XAML的例子),结合工程和执行该命令。
Apparently, I "just" need to tell the button to bind to the main ViewModel of the form.
But I'm not able to figure out the right XAML syntax.
显然,我“只是”需要告诉按钮绑定到表单的主 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}}}" />
Could someone please:
有人可以请:
- give me the proper XAML to bind the button inside the
ListBoxto 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 needRelativeSourceorStaticResourceor whatever instead of a "normal" binding.
- 给我合适的 XAML 来将里面的按钮绑定
ListBox到表单中的命令MainViewModel? - 将我指向一个链接,其中以 WPF/MVVM 初学者可以理解的方式解释了这种高级绑定内容?
我觉得我只是在复制和粘贴神秘的 XAML 咒语,到目前为止我没有任何线索(并且找不到任何好的文档)我如何自己弄清楚在哪些情况下我需要RelativeSource或StaticResource或其他任何东西,而不是“正常”绑定。
采纳答案by H.B.
It's:
它的:
{Binding DataContext.FireCommand,
RelativeSource={RelativeSource AncestorType=ListBox}}
No need to walk up to the root unless you actually change the DataContextalong the way, but as the ListBoxseems to bind to a property on the main VM this should be enough.
无需走到根目录,除非您DataContext沿途实际更改,但由于ListBox似乎绑定到主 VM 上的属性,这应该就足够了。
The only thing i recommend reading is the Data Binding Overview, and the Bindingclassdocumentation (including its properties).
我唯一推荐阅读的是数据绑定概述和Binding类文档(包括其属性)。
Also here is a short explanation on how bindings are constructed: A binding consists of a sourceand a Pathrelative to that source, by default the sourceis the current DataContext. Sources that can be set explicitly are: Source, ElementName& RelativeSource. Setting any of those will override the DataContextas source.
这里还有一个关于如何构建绑定的简短解释:绑定由一个source和一个Path相对于该source 的 source 组成,默认情况下,source是 current DataContext。可以明确设置的来源是:Source, ElementName& RelativeSource。设置其中任何一个都将覆盖DataContextas source。
So if you use a sourcelike RelativeSourceand want to access something in the DataContexton that level the DataContextneeds to appear in the Path.
因此,如果您使用类似的源RelativeSource并希望访问DataContext该级别中的某些内容,则DataContext需要出现在Path.
回答by smoovey
This may be considered unrelated by most, but this search is only 1 of 3 results that you'll find searching for data binding commands to controls inside a data template--as it relates to Xamarin Forms. So, maybe it'll help someone now-a-days.
大多数人可能认为这不相关,但此搜索只是搜索数据模板内控件的数据绑定命令的 3 个结果中的 1 个,因为它与 Xamarin Forms 相关。所以,也许它会帮助现在的人。
Like me you may wonder how to bind commands inside a BindableLayout. Credit jesulink2514 for answering this at Xamarin Forums, where it's probably overlooked by many because of all the comments. Here's his solution, but I'm including the link below:
像我一样,您可能想知道如何在 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
https://forums.xamarin.com/discussion/comment/217355/#Comment_217355

