将 DataTemplate 中的按钮绑定到表单的 ViewModel 中的命令
Posted
技术标签:
【中文标题】将 DataTemplate 中的按钮绑定到表单的 ViewModel 中的命令【英文标题】:Bind button in DataTemplate to command in the form's ViewModel 【发布时间】:2012-09-03 20:14:24 【问题描述】:我的问题与这个问题中描述的类似: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<string>
(在 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");
此按钮的绑定不起作用。 根据我从上面链接的question 中了解到的情况,绑定不起作用,因为:(如果我错了,请纠正我)
按钮位于ListBox
内,因此它只“知道”ListBox
的绑定(在本例中为ObservableCollection
),而不是主窗口的绑定
我正在尝试绑定到主窗口的主 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" />
有人可以吗:
-
给我正确的 XAML 以将
ListBox
中的按钮绑定到表单的 MainViewModel
中的命令?
指向一个链接,其中以 WPF/MVVM 初学者可以理解的方式解释了这种高级绑定内容?我觉得我只是在复制和粘贴神秘的 XAML 咒语,并且到目前为止,我没有任何线索(也找不到任何好的文档)我将如何自己弄清楚在哪些情况下我需要 RelativeSource
或 StaticResource
或其他任何东西而不是“正常”绑定。
【问题讨论】:
【参考方案1】:是:
Binding DataContext.FireCommand,
RelativeSource=RelativeSource AncestorType=ListBox
除非您实际上更改了DataContext
,否则无需走到根目录,但由于ListBox
似乎绑定到主VM 上的属性,这应该足够了。
我唯一推荐阅读的是Data Binding Overview 和Binding
class 文档(包括其属性)。
这里还有一个关于如何构造绑定的简短说明:绑定由 source 和相对于该 source 的 Path
组成>,默认情况下 source 是当前的DataContext
。可以显式设置的来源是:Source
、ElementName
和 RelativeSource
。设置其中任何一个都将覆盖DataContext
作为源。
因此,如果您使用像RelativeSource
这样的源 并希望在该级别访问DataContext
中的某些内容,则DataContext
需要出现在Path
中 em>。
【讨论】:
很好的答案,这有帮助。谢谢! 谢谢——四个小时的调试终于结束了!顺便说一句,它也适用于Binding DataContext.FireCommand, ElementName=root
,假设您为UserControl
设置了x:Name="root"
。我认为这稍微优雅一些。
@Informagic:除非您的 IDE 可以在重命名元素时更新绑定,否则我建议使用相对源绑定。如果您过度使用名称引用并绑定到“很远”的元素,名称引用也会使理解标记变得困难。
在我的场景中,与Binding RelativeSource=RelativeSource FindAncestor, AncestorType=x:Type ListBox, Path=DataContext.FireCommand
合作希望这可以帮助某人。
@Peter-Yu:在大多数情况下是等价的。您只需直接设置Path
属性。在我的回答中,路径被传递给 Binding
构造函数,该构造函数在内部设置 Path
属性。 (虽然有一些实现细节在使用构造函数时可能会导致问题。)【参考方案2】:
这可能被大多数人认为是不相关的,但此搜索只是 3 个结果中的一个,您会发现这些结果用于搜索数据模板内的控件的数据绑定命令 - 因为它与 Xamarin Forms 相关。所以,也许它现在对某人有帮助。
像我一样,您可能想知道如何在 BindableLayout 中绑定命令。感谢 jesulink2514 在 Xamarin 论坛上回答这个问题,由于所有的 cmets,它可能被许多人忽略了。这是他的解决方案,但我包括以下链接:
<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
【讨论】:
作为附加资源,此链接中的代码适用于我的情况:syncfusion.com/kb/11029/…以上是关于将 DataTemplate 中的按钮绑定到表单的 ViewModel 中的命令的主要内容,如果未能解决你的问题,请参考以下文章
UWP 数据绑定:如何将按钮命令设置为 DataTemplate 中的父 DataContext
如何将 ObservableCollection 绑定到 DataTemplate 中的文本框?