WPF MVVM ListBox 中的多项选择
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/34630406/
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
Multiple selection in WPF MVVM ListBox
提问by Michal
I have a ListBox containing filenames. Now I need to get array of selected items from this ListBox. I found a few answers here, but none of them worked for me. I'am using Caliburn Micro framework.
我有一个包含文件名的 ListBox。现在我需要从这个 ListBox 中获取所选项目的数组。我在这里找到了一些答案,但没有一个对我有用。我正在使用 Caliburn Micro 框架。
Here is my View:
这是我的观点:
<Window x:Class="ProgramsAndUpdatesDesktop.Views.DeleteHistoryView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ProgramsAndUpdatesDesktop.Views"
mc:Ignorable="d"
ResizeMode="CanResizeWithGrip"
MaxWidth="300"
MinWidth="300"
MinHeight="500"
Title="DeleteHistoryView" Height="500" Width="300">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="30" />
</Grid.RowDefinitions>
<StackPanel Grid.Column="0" Grid.Row="0">
<ListBox x:Name="DeleteHistoryListBox" SelectedItem="{Binding Path=DeleteHistorySelectedItem}"
ItemsSource="{Binding DeleteHistoryListBox, NotifyOnSourceUpdated=True}"
SelectionMode="Multiple">
</ListBox>
</StackPanel>
<StackPanel Grid.Column="0" Grid.Row="1">
<Button x:Name="DeleteHistoryButtonAction">Delete</Button>
</StackPanel>
</Grid>
And here is my ViewModel:
这是我的 ViewModel:
class DeleteHistoryViewModel : Screen
{
string historyFolderPath = Environment.ExpandEnvironmentVariables(ConfigurationManager.AppSettings["HistoryFolderPath"]);
private ObservableCollection<string> deleteHistoryListBox = new ObservableCollection<string>();
public ObservableCollection<string> DeleteHistoryListBox
{
get { return deleteHistoryListBox; }
set { deleteHistoryListBox = value; NotifyOfPropertyChange(() => DeleteHistoryListBox); }
}
private List<string> deleteHistorySelectedItem = new List<string>();
public List<string> DeleteHistorySelectedItem
{
get { return deleteHistorySelectedItem; }
set { deleteHistorySelectedItem = value; }
}
public DeleteHistoryViewModel()
{
base.DisplayName = "Delete History";
}
protected override void OnInitialize()
{
FillListBox();
}
private void FillListBox()
{
string[] directory = Directory.GetFiles($"{historyFolderPath}\", "*.json");
foreach (var item in directory)
{
string fileName = System.IO.Path.GetFileName(item).ToString();
if (!DeleteHistoryListBox.Contains(fileName))
{
DeleteHistoryListBox.Add(fileName);
}
}
}
#region ACTIONS REGION
// DELETE HISTORY ACTION
public void DeleteHistoryButtonAction()
{
foreach (var item in DeleteHistorySelectedItem)
{
MessageBox.Show(item);
}
}
#endregion
}
回答by Justin CI
You can use this code for MVVM Pattern
您可以将此代码用于 MVVM 模式
XAML
XAML
<ListBox x:Name="DeleteHistoryListBoxItem" SelectedItem="{Binding Path=DeleteHistorySelectedItem,UpdateSourceTrigger=PropertyChanged}"
ItemsSource="{Binding DeleteHistoryListBox, NotifyOnSourceUpdated=True}" SelectionMode="Multiple">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Item}"/>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="IsSelected" Value="{Binding Mode=TwoWay, Path=IsSelected}"/>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
ViewModel
视图模型
private ObservableCollection<HistoryItems> deleteHistoryListBox = new ObservableCollection<HistoryItems>();
public ObservableCollection<HistoryItems> DeleteHistoryListBox
{
get
{
return deleteHistoryListBox;
}
set
{
deleteHistoryListBox = value;
this.RaisePropertyChanged("DeleteHistoryListBox");
}
}
private HistoryItems deleteHistorySelectedItem;
public HistoryItems DeleteHistorySelectedItem
{
get
{
return deleteHistorySelectedItem;
}
set
{
var selectedItems = DeleteHistoryListBox.Where(x => x.IsSelected).Count();
this.RaisePropertyChanged("DeleteHistorySelectedItem");
}
}
Class
班级
public class HistoryItems : INotifyPropertyChanged
{
private string item;
public string Item
{
get { return item; }
set
{
item = value;
this.RaisePropertyChanged("Item");
}
}
private bool isSelected;
public bool IsSelected
{
get { return isSelected; }
set
{
isSelected = value;
this.RaisePropertyChanged("IsSelected");
}
}
}
回答by Anton Danylov
You can add SelectionChanged event handler in code-behind, and update property for selected items in the ViewModel from there.
您可以在代码隐藏中添加 SelectionChanged 事件处理程序,并从那里更新 ViewModel 中所选项目的属性。
XAML:
XAML:
<ListBox x:Name="DeleteHistoryListBox" SelectedItem="{Binding Path=DeleteHistorySelectedItem}"
ItemsSource="{Binding DeleteHistoryListBox, NotifyOnSourceUpdated=True}"
SelectionMode="Multiple" SelectionChanged="DeleteHistoryListBox_SelectionChanged">
</ListBox>
DeleteHistoryView.xaml.cs
删除历史视图.xaml.cs
private void DeleteHistoryListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
DeleteHistoryViewModel vm = (DeleteHistoryViewModel)DataContext;
foreach (string item in e.AddedItems)
{
vm.DeleteHistorySelectedItem.Add(item);
}
foreach (string item in e.RemovedItems)
{
vm.DeleteHistorySelectedItem.Remove(item);
}
}

