通用的可编辑标签

时间:2015-09-03 06:59:15

标签: c# wpf

我正在实施一种重命名window.onkeydown=function(e){ if(e.keycode==34 || e.keycode==32){ e.preventDefault(); } } 中元素的方法。我的想法不是建立一个特殊的treeview,而是一个特殊的TreeView,它也可以在Label和其他控件中使用。它通过点击将焦点设置为自身,因此我将ListBox更改为Focusable。如果专注,可以通过 [F2] 进行编辑,并在已经拥有焦点时点击它。可编辑的意思是一个文本框显示(所有类似于Windows资源管理器)。不幸的是,当我点击true时,TreeViewItem没有被选中。单击左侧的图标时,会选择label

我没有处理任何事件设置TreeViewItem,但我认为Handled=true本身会处理点击,因此Label没有机会对其做出反应。如果我就在这里,有没有办法以一种它根本不处理事件的方式修改标签(自己的类?)?

1 个答案:

答案 0 :(得分:0)

我重新考虑了我的尝试。解决方案根本不是重点。相反,我将处理程序绑定到当前具有焦点的观察元素的KeyUp事件(请参阅EditableLabel.cs中的注释)。

EditableLabel.xaml:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:myown.Wpf"
                    xmlns:localCtrls="clr-namespace:myown.Wpf.Controls">
    <Style TargetType="{x:Type localCtrls:EditableLabel}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type localCtrls:EditableLabel}">
                    <StackPanel>
                        <Label x:Name="label" 
                                            Content="{TemplateBinding Text}" 
                                            Visibility="Visible"
                                            Height="{TemplateBinding Height}"
                                            Width="{TemplateBinding Width}"
                                            Padding="{TemplateBinding Padding}"
                                            Foreground="{TemplateBinding Foreground}"/>

                        <!-- TemplateBinding is always OneWay! -->

                        <TextBox x:Name="textbox" 
                                 Text="{Binding Path=Text, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"  
                                 Visibility="Collapsed"
                                 Height="{TemplateBinding Height}"
                                 Width="{TemplateBinding Width}"
                                 Padding="{TemplateBinding Padding}"/>
                    </StackPanel>
                </ControlTemplate>
            </Setter.Value>

        </Setter>
    </Style>
</ResourceDictionary>

EditableLabel.cs:

public partial class EditableLabel : Label
{

    #region DependencyProperties

    public static readonly DependencyProperty IsEditingProperty =
        DependencyProperty.Register("IsEditing", typeof(bool), typeof(EditableLabel),
        new UIPropertyMetadata(false, IsEditingUpdate));

    public static readonly DependencyProperty TextProperty =
        DependencyProperty.Register("Text", typeof(string), typeof(EditableLabel),
         new FrameworkPropertyMetadata("",
             FrameworkPropertyMetadataOptions.AffectsRender |
             FrameworkPropertyMetadataOptions.AffectsParentMeasure |
             FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

    public bool IsEditing
    {
        get { return (bool)GetValue(IsEditingProperty); }
        set { SetValue(IsEditingProperty, value); }
    }

    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }

    private string m_lastValue = "";
    private IInputElement m_lastFocus = null;

    private Label m_label = null;
    private TextBox m_textBox = null;

    #endregion

    static EditableLabel()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(EditableLabel),
            new FrameworkPropertyMetadata(typeof(EditableLabel)));
    }

    public EditableLabel()
    {
        LostFocus += (s, e) => { };
        LostKeyboardFocus += EditableLabel_LostKeyboardFocus;
    }

    private void EditableLabel_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
    {
        if (e.NewFocus != null)
            Debug.WriteLine(e.NewFocus.GetType().Name);
    }

    public override void OnApplyTemplate()
    {
        m_label = GetTemplateChild("label") as Label;
        m_textBox = GetTemplateChild("textbox") as TextBox;

        m_label.MouseUp += Label_MouseUp;
        m_textBox.LostFocus += (s, e) => IsEditing = false;
        m_textBox.KeyUp += (s, e) => { TextBox_KeyUp(s, e); e.Handled = true; };
        m_textBox.GotKeyboardFocus += (s, e) => m_textBox.SelectAll();

        base.OnApplyTemplate();
    }

    private void Label_MouseUp(object sender, MouseButtonEventArgs e)
    {
        DependencyObject scope = FocusManager.GetFocusScope(this);
        IInputElement currFocus = FocusManager.GetFocusedElement(scope);

        if ((currFocus != null))
        {
            if (currFocus == m_lastFocus)
            {
                IsEditing = true;
            }
            else
            {
                m_lastFocus = currFocus;
                DependencyObject observedObject = currFocus as DependencyObject;
                if (observedObject != null)
                {
                    m_lastFocus.LostKeyboardFocus += ObservedElementLostFocus;
                    m_lastFocus.KeyUp += ObservedElement_KeyUp; // THIS IS THE TRICK
                }
            }
        }
    }

    private void ObservedElement_KeyUp(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.F2)
        {
            IsEditing = true;
            e.Handled = true;
        }
    }

    private void ObservedElementLostFocus(object sender, RoutedEventArgs e)
    {
        KeyboardFocusChangedEventArgs kfc = e as KeyboardFocusChangedEventArgs;
        if (kfc.NewFocus != null)
        {
            if ((kfc.NewFocus != m_textBox) && (kfc.NewFocus != m_lastFocus))
            {
                m_lastFocus.LostKeyboardFocus -= ObservedElementLostFocus;
                m_lastFocus.KeyUp -= ObservedElement_KeyUp;
                m_lastFocus = null;
            }
        }
    }

    private void TextBox_KeyUp(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.Escape)
        {
            IsEditing = false;
            Text = m_lastValue;
        }
        else if (e.Key == Key.Enter)
        {
            IsEditing = false;
        }
    }

    private static void IsEditingUpdate(DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        EditableLabel self = obj as EditableLabel;
        if ((bool)e.NewValue)
        {
            self.m_lastValue = self.Text;
            self.m_textBox.Visibility = Visibility.Visible;
            self.m_textBox.Focus();
            self.m_label.Visibility = Visibility.Collapsed;
        }
        else
        {
            self.m_textBox.Visibility = Visibility.Collapsed;
            self.m_label.Visibility = Visibility.Visible;
            if (self.m_lastFocus != null)
                self.m_lastFocus.Focus();
        }
    }
}