[英]WPF: How to bind a command to the ListBoxItem using MVVM?
我剛剛開始學習MVVM。 我已經按照該MVVM教程從頭開始制作了該應用程序(我強烈推薦該應用程序供所有MVVM初學者使用)。 基本上,到目前為止,我已經創建了幾個文本框,用戶可以在其中添加他或她的數據,這是一個用於保存該數據的按鈕,該按鈕隨后將所有輸入內容填充到ListBox中。
這是我遇到的問題:我希望能夠雙擊ListBoxItem並觸發我創建並添加到ViewModel的命令。 我不知道如何完成XAML方面,即我不知道如何將該命令綁定到ListBox(Item)。
這是XAML:
...
<ListBox
Name="EntriesListBox"
Width="228"
Height="208"
Margin="138,12,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
ItemsSource="{Binding Entries}" />
...
這是ViewModel:
public class MainWindowViewModel : DependencyObject
{
...
public IEntriesProvider Entries
{
get { return entries; }
}
private IEntriesProvider entries;
public OpenEntryCommand OpenEntryCmd { get; set; }
public MainWindowViewModel(IEntriesProvider source)
{
this.entries = source;
...
this.OpenEntryCmd = new OpenEntryCommand(this);
}
...
}
最后,這是一旦用戶雙擊EntriesListBox中的項目,我要執行的OpenEntryCommand:
public class OpenEntryCommand : ICommand
{
private MainWindowViewModel viewModel;
public OpenEntryCommand(MainWindowViewModel viewModel)
{
this.viewModel = viewModel;
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public bool CanExecute(object parameter)
{
return parameter is Entry;
}
public void Execute(object parameter)
{
string messageFormat = "Subject: {0}\nStart: {1}\nEnd: {2}";
Entry entry = parameter as Entry;
string message = string.Format(messageFormat,
entry.Subject,
entry.StartDate.ToShortDateString(),
entry.EndDate.ToShortDateString());
MessageBox.Show(message, "Appointment");
}
}
請幫忙,不勝感激。
不幸的是,只有ButtonBase
派生的控件才可以將ICommand
對象綁定到其Command
屬性(對於Click
事件)。
但是,您可以使用Blend提供的API將事件(例如您在ListBox
上的MouseDoubleClick
) MouseDoubleClick
到ICommand
對象。
<ListBox>
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDoubleClick">
<i:InvokeCommandAction Command="{Binding YourCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ListBox>
您必須定義: xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
並具有對System.Windows.Interactivity.dll
的引用。
-編輯-這是WPF4的一部分,但是如果您不使用WPF4,則可以使用Microsoft.Windows.Interactivity。 該dll來自Blend SDK,不需要Blend,可從以下位置獲取 : http : //www.microsoft.com/downloads/zh-CN/details.aspx? FamilyID=f1ae9a30-4928-411d-970b-e682ab179e17&displaylang =en
更新 :我發現了一些可以幫助您的東西。 請查看MVVM Light Toolkit上的此鏈接,其中包含有關如何執行此操作的演練,以及指向所需庫的鏈接 。 MVVM Light Toolkit是一個非常有趣的框架,用於將MVVM與Silverlight,WPF和WP7一起應用。
希望這可以幫助 :)
由於DoubleClick事件,這變得棘手。 有幾種方法可以做到這一點:
2和3可能更純凈,但坦率地說,1更容易,更簡單,而不是世界上最糟糕的事情。 對於一次性的情況,我可能會使用方法1。
現在,如果您更改了要在每個項目上使用超鏈接的要求,那將變得更加容易。 首先在XAML中命名根元素-例如,對於Window:
<Window .... Name="This">
現在,在您的ListBox項的DataTemplate中,使用如下所示的內容:
<ListBox ...>
<ListBox.ItemTemplate>
<DataTemplate>
<Hyperlink
Command="{Binding ElementName=This, Path=DataContext.OpenEntryCmd}"
Text="{Binding Path=Name}"
/>
ElementName綁定使您可以從ViewModel的上下文而不是特定的數據項中解析OpenEntryCmd。
我發現最好的方法是為我的內容創建一個簡單的用戶控件包裝,並為命令和參數添加依賴項屬性。
我這樣做的原因是因為Button不能將click事件冒泡到我的ListBox中,這阻止了它選擇ListBoxItem。
CommandControl.xaml.cs:
public partial class CommandControl : UserControl
{
public CommandControl()
{
MouseLeftButtonDown += OnMouseLeftButtonDown;
InitializeComponent();
}
private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs mouseButtonEventArgs)
{
if (Command != null)
{
if (Command.CanExecute(CommandParameter))
{
Command.Execute(CommandParameter);
}
}
}
public static readonly DependencyProperty CommandProperty =
DependencyProperty.Register("Command", typeof(ICommand),
typeof(CommandControl),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.None));
public ICommand Command
{
get { return (ICommand)GetValue(CommandProperty); }
set { SetValue(CommandProperty, value); }
}
public static readonly DependencyProperty CommandParameterProperty =
DependencyProperty.Register("CommandParameter", typeof(object),
typeof(CommandControl),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.None));
public object CommandParameter
{
get { return (object)GetValue(CommandParameterProperty); }
set { SetValue(CommandParameterProperty, value); }
}
}
CommandControl.xaml:
<UserControl x:Class="WpfApp.UserControls.CommandControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
Background="Transparent">
</UserControl>
用法:
<ListBoxItem>
<uc:CommandControl Command="{Binding LoadPageCommand}"
CommandParameter="{Binding HomePageViewModel}">
<TextBlock Text="Home" Margin="0,0,0,5" VerticalAlignment="Center"
Foreground="White" FontSize="24" />
</uc:CommandControl>
</ListBoxItem>
內容可以是任何內容,當單擊控件時,它將執行命令。
編輯:向UserControl添加Background="Transparent"
以在控件的整個區域上啟用單擊事件。
這是一個小技巧,但效果很好,並允許您使用命令並避免出現背后的代碼。 這還具有一個額外的好處,即在您的ListBoxItems
不會填充整個容器的情況下,在空白ScrollView
區域中雙擊(或您的觸發器是什么)時,不觸發命令。
基本上,只要創建一個DataTemplate
為你的ListBox
,它由一個中TextBlock
和寬度結合TextBlock
的寬度ListBox
,設置邊距和填充為0,並禁用水平滾動(因為TextBlock
會流血超過可見ScrollView
邊界觸發水平滾動條)。 我發現的唯一錯誤是,如果用戶恰好單擊了我可以使用的ListBoxItem
的邊框,該命令將不會觸發。
這是一個例子:
<ListBox
x:Name="listBox"
Width="400"
Height="150"
ScrollViewer.HorizontalScrollBarVisibility="Hidden"
ItemsSource="{Binding ItemsSourceProperty}"
SelectedItem="{Binding SelectedItemProperty}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Padding="0"
Margin="0"
Text="{Binding DisplayTextProperty}"
Width="{Binding ElementName=listBox, Path=Width}">
<TextBlock.InputBindings>
<MouseBinding
Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBox}}, Path=DataContext.SelectProjectCommand}"
Gesture="LeftDoubleClick" />
</TextBlock.InputBindings>
</TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.