WPF:ListView和编辑ListViewItem

在此处输入图像描述

我希望能够选择一个项目,然后编辑其标签:

  • 选择一个项目
  • 项目突出显示
  • 点击它的标签
  • Label的TextBlock替换为TextBox
  • 修改标签
  • 一次只能编辑一个项目

结束编辑:

  1. 点击项目的图标:
    • TextBox将替换为TextBlock
    • 项目仍然突出显示
  2. 点击另一个项目:
    • TextBox将替换为TextBlock
    • 已编辑的项目未被选中
    • 选中并突出显示单击的项目
  3. 单击窗口的任何其他区域:
    • TextBox将替换为TextBlock
    • 编辑的项目仍然突出显示

该行为应该与Windows资源管理器中的行为非常相似。

我设法完成了大部分要求。 我仍然得到随机结果。 例如,在第一次启动时,我可以直接点击标签进行编辑。 项目本身仍未突出显示。 这仅在开始时发生。

使用滚动条也不会将焦点从列表项中移除。 这允许同时编辑多个项目。

XAML

                                          

 public partial class DailyImages { public DailyImages() { InitializeComponent(); ViewModel.DailyImages dailyImages = new ViewModel.DailyImages(); _mediaItemList.DataContext = dailyImages; } private void OnClickLabelBlock(object sender, MouseButtonEventArgs e) { TextBlock notes = sender as TextBlock; if (notes == null) return; MediaItem selectedMedia = notes.DataContext as MediaItem; if (selectedMedia == null) return; // Multiple items might be selected // Clear all selected items _mediaItemList.SelectedItems.Clear(); // Reselect selectedMedia.IsSelected = true; selectedMedia.IsEditing = true; Mouse.Capture(this, CaptureMode.SubTree); } private void OnTextLostFocus(object sender, RoutedEventArgs e) { TextBox textBox = sender as TextBox; if (textBox == null) return; MediaItem mediaItem = textBox.DataContext as MediaItem; if (mediaItem == null) return; // End the label editing mediaItem.IsEditing = false; ReleaseMouseCapture(); } private void OnClickMediaList(object sender, MouseButtonEventArgs e) { // End the label editing foreach (MediaItem mediaItem in _mediaItemList.Items) mediaItem.IsEditing = false; ReleaseMouseCapture(); } } 

MediaItem.cs

 public class MediaItem : INotifyPropertyChanged { private bool _isEditing; private bool _isSelected; private string _label; public MediaItem() { IsEditing = false; _isSelected = false; } public bool IsEditing { get { return _isEditing; } set { if (_isEditing == value) return; _isEditing = value; OnPropertyChanged("IsEditing"); } } public string Label { get { return _label; } set { _label = value; OnPropertyChanged("Label"); } } public DateTime Date { get; set; } public string IconPath { get; set; } public bool IsSelected { get { return _isSelected; } set { _isSelected = value; OnPropertyChanged("IsSelected"); } } public event PropertyChangedEventHandler PropertyChanged; [NotifyPropertyChangedInvocator] protected virtual void OnPropertyChanged(string propertyName) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); } } 

DailyImages.cs

 public class DailyImages { private ObservableCollection _mediaItems; public DailyImages() { _mediaItems = new ObservableCollection(); _mediaItems.Add(new MediaItem {Label = "Image 1", IconPath = "Resources/Icon1.png"}); _mediaItems.Add(new MediaItem {Label = "Image 2", IconPath = "Resources/Icon2.png"}); _mediaItems.Add(new MediaItem {Label = "Image 3", IconPath = "Resources/Icon3.png"}); _mediaItems.Add(new MediaItem {Label = "Image 4", IconPath = "Resources/Icon4.png"}); _mediaItems.Add(new MediaItem {Label = "Image 5", IconPath = "Resources/Icon5.jpg"}); _mediaItems.Add(new MediaItem {Label = "Image 6", IconPath = "Resources/Icon6.png"}); _mediaItems.Add(new MediaItem {Label = "Image 7", IconPath = "Resources/Icon7.png"}); _mediaItems.Add(new MediaItem {Label = "Image 8", IconPath = "Resources/Icon8.png"}); _mediaItems.Add(new MediaItem {Label = "Image 9", IconPath = "Resources/Icon9.png"}); } public ObservableCollection MediaItems { get { return _mediaItems; } set { _mediaItems = value; } } } 

感谢阅读长篇文章。

我在StackOverflow中搜索并阅读了很多答案,但这些答案对我来说都不是很好。

例如:

  • 控件如何在该控件外部处理鼠标单击?
  • 单击空白区域时如何处理事件?
  • 如何捕获鼠标单击WPF中ListBox中的项目?

您可能希望捕获listview上的scrollevent并显式删除对元素的焦点。

  ScrollViewer scrollViewer = GetVisualChild(mTreeView); scrollViewer.ScrollChanged += new ScrollChangedEventHandler(scrollViewer..... 

并在处理程序内删除焦点。

查看此stackoverflow页面,以便将焦点从元素WPF移开:如何以编程方式从TextBox中删除焦点

也许最好将IsReadonly属性切换到不同的状态? 然后,您将不再需要切换可见性。 此外,在这种情况下更换模板更好。