如何(完全)在 ListBox 中实现就地编辑? [英] How do I (fully) implement in-place editing in a ListBox?

查看:31
本文介绍了如何(完全)在 ListBox 中实现就地编辑?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在构建一个应用程序,其中 ListBox 显示其项目的 Description 属性.我想实现与您在 Windows 资源管理器中编辑文件名时会发现的相同类型的就地编辑功能,我发现这需要大量工作.

I'm building an application where a ListBox is displaying the Description properties of its items. I want to implement the same kind of edit-in-place functionality that you'd find, say, when editing filenames in Windows Explorer, and I'm finding it to be a whole lot of work.

到目前为止,我拥有的是一个启动编辑的 ContextMenu.它绑定到视图模型中设置 IsEditingDescription 属性的命令.项目模板的样式设置为当 IsEditingDescription 为 false 时在 TextBlockTextBox 中显示 Description> 当 IsEditingDescription 为真时.Description 上的 setter 在设置说明后将 IsEditingDescription 设置为 false.

What I have so far is a ContextMenu that initiates the edit. It's bound to a command in the view model that sets an IsEditingDescription property. The item template is styled so that it displays the Description in a TextBlock when IsEditingDescription is false, and in a TextBox when IsEditingDescription is true. The setter on Description sets IsEditingDescription to false after setting the description.

这非常有效.但有些事情它不应该做:

This works remarkably well. But there are some things that it doesn't do that it should:

  • 用户应该能够通过按 F2 启动编辑.
  • 用户应该能够通过按 ESC 取消编辑.
  • 用户应该能够通过按 ENTER 确认编辑.
  • 当用户第二次点击当前选择的项目时,它应该启动编辑.
  • 出现文本框时应选择描述文本

我想我可以用命令和键绑定处理前三项,尽管我还不太了解如何进行键绑定.但我真的想不出一个 MVVMish 的方式来做另外两个.有吗?

I think I can handle the first three items with commands and key bindings, though I don't really understand how to do key bindings yet. But I can't really figure out an MVVMish way to do the other two. Is there one?

推荐答案

这是我不得不一遍又一遍地做的事情,所以我决定扩展 ListView 控件并添加 ItemKeyDown、ItemKeyUp 和 ItemDoubleClick 事件,这些事件在这些事件发生的地方被触发当 ListView 中的项目处于焦点时发生.ListView 派生自一个 ListBox,因此您应该能够很容易地移植它.

this was something I was having to do over and over so I decided to extend the ListView control and added ItemKeyDown, ItemKeyUp and ItemDoubleClick events which are fired where those events occur when an item in the ListView is in focus. The ListView is derived a ListBox so you should be able to port it over pretty easily.

/Fx/ListView.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Controls;

namespace Fx
{
    public static class Func
    {
        /// <summary>
        /// Finds a specific type of parent up the visual tree.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dep"></param>
        /// <returns></returns>
        public static T FindParent<T>(this object obj)
        {
            DependencyObject dep = obj as DependencyObject;
            while ((dep != null) && !(dep is T))
            {
                dep = VisualTreeHelper.GetParent(dep);
            }
            return (dep != null) ? (T)Convert.ChangeType(dep, typeof(T)) : default(T);
        }
    }

    public class ListView:System.Windows.Controls.ListView
    {

        #region public event KeyboardEventHandler ItemKeyDown;
        /// <summary>
        /// Occurs when a key is pressed when a ListViewItem in this
        /// ListView is in focus.
        /// </summary>
        public event KeyEventHandler ItemKeyDown;

        /// <summary>
        /// Raises the ItemKeyDown event for a ListViewitem in this ListView.
        /// </summary>
        /// <param name="item"></param>
        /// <param name="e"></param>
        public void OnItemKeyDown(ListViewItem item, KeyEventArgs e)
        {
            if (ItemKeyDown != null)
                ItemKeyDown(item, e);
        }

        /// <summary>
        /// Handle they KeyDown event on the ListView, find the related
        /// ListViewItem and raise the ItemKeyDown event respectively.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ListView_KeyDown(object sender, KeyEventArgs e)
        {
            ListViewItem item = Func.FindParent<ListViewItem>(e.OriginalSource);
            if (item != null)
                OnItemKeyDown(item, e);
        }
        #endregion

        #region public event KeyboardEventHandler ItemKeyUp;
        /// <summary>
        /// Occurs when a key is released when a ListViewItem in this
        /// ListView is in focus.
        /// </summary>
        public event KeyEventHandler ItemKeyUp;

        /// <summary>
        /// Raises the ItemKeyUp event for a ListViewitem in this ListView.
        /// </summary>
        /// <param name="item"></param>
        /// <param name="e"></param>
        public void OnItemKeyUp(ListViewItem item, KeyEventArgs e)
        {
            if (ItemKeyUp != null)
                ItemKeyUp(item, e);
        }

        /// <summary>
        /// Handle they KeyUp event on the ListView, find the related
        /// ListViewItem and raise the ItemKeyUp event respectively.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ListView_KeyUp(object sender, KeyEventArgs e)
        {
            ListViewItem item = Func.FindParent<ListViewItem>(e.OriginalSource);
            if (item != null)
                OnItemKeyUp(item, e);
        }
        #endregion

        #region public event MouseButtonEventHandler ItemDoubleClick;
        /// <summary>
        /// Occurs when a ListViewItem in this Listview is double clicked.
        /// </summary>
        public event MouseButtonEventHandler ItemDoubleClick;

        /// <summary>
        /// Raise the ItemDoubleClick event for a ListViewItem.
        /// </summary>
        /// <param name="item"></param>
        /// <param name="e"></param>
        public void OnItemDoubleClick(ListViewItem item, MouseButtonEventArgs e)
        {
            if (ItemDoubleClick != null)
                ItemDoubleClick(item, e);
        }

        /// <summary>
        /// Handle the MouseDoubleClick event for the ListView, find the related
        /// ListViewItem and raise the ItemDoubleClick event respectively.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ListView_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            ListViewItem item = Func.FindParent<ListViewItem>(e.OriginalSource);
            if (item != null)
                OnItemDoubleClick(item, e);
        }
        #endregion

        public ListView()
        {
            MouseDoubleClick += new MouseButtonEventHandler(ListView_MouseDoubleClick);
            KeyDown += new KeyEventHandler(ListView_KeyDown);
            KeyUp += new KeyEventHandler(ListView_KeyUp);
        }
    }
}

现在使用它.../Pages/EmployeesPage.xaml

<UserControl x:Class="TestApp.Pages.EmployeesPage"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:fx="clr-namespace:Fx"
             Width="800" Height="450">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="300" />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <StackPanel Grid.Column="0">
            <TextBlock Text="List Items" FontWeight="Bold" FontSize="18" />

            <!-- here is the main part -->
            <fx:ListView x:Name="EmployeesList" ItemDoubleClick="EmployeesList_ItemDoubleClick" ItemKeyDown="EmployeesList_ItemKeyDown" />
            <!-- main part ends here -->

        </StackPanel>
    </Grid>
</UserControl>

/Pages/EmployeesPage.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace TestApp.Pages
{
    /// <summary>
    /// Interaction logic for EmployeesPage.xaml
    /// </summary>
    public partial class EmployeesPage : UserControl
    {
        public EmployeesPage()
        {
            InitializeComponent();

            // Fill the ListView with data...
            // EmployeesList.ItemsSource = SomeObservableCollectionOrDataSource
        }

        private void EmployeesList_ItemDoubleClick(object sender, MouseButtonEventArgs e)
        {
            MessageBox.Show("an item was double clicked");

            ListViewItem item = sender as ListViewItem;
            // entityType obj = item.DataContext as entityType

            // you can begin editing here
        }

        private void EmployeesList_ItemKeyDown(object sender, KeyEventArgs e)
        {
            MessageBox.Show(e.Key.ToString() + " key was pressed on an item");

            ListViewItem item = sender as ListViewItem;
            // entityType obj = item.DataContext as entityType

            if (e.Key == Key.F2)
            {
                // begin editing here
            }
            else if (e.Key == Key.Enter)
            {
                // end editing here
            }
            else if (e.Key == Key.Escape)
            {
                // cancel editing here
            }
        }
    }
}

希望这至少对你有用..祝你好运.

Hope this is of at least some use to you.. Good luck.

这篇关于如何(完全)在 ListBox 中实现就地编辑?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆