文档章节

WPF下可编辑Header的Tab控件实现

葡萄城技术团队
 葡萄城技术团队
发布于 2014/06/11 12:16
字数 659
阅读 26
收藏 0

介绍

有这样一个需求,当用户双击Tab控件Header区域时, 希望可以直接编辑。对于WPF控件,提供一个ControlTemplate在加上一些Trigger就可以实现。效果如下:

 

 

代码

首先,我们需要给Tab Header设计一个ControlTemplate。类似一个TextBlock,双击进入编辑状态。 所以Xaml如下:

 


  
  1. <Setter Property="Template"> 
  2.                 <Setter.Value> 
  3.                     <ControlTemplate TargetType="{x:Type local:EditableTabHeaderControl}"> 
  4.                         <Grid> 
  5.                             <TextBox x:Name="PART_TabHeader" Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content, Mode=TwoWay}" Visibility="Collapsed"/> 
  6.                             <TextBlock x:Name="PART_TextBlock" Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content, Mode=TwoWay}"/> 
  7.                         </Grid> 
  8.                         <ControlTemplate.Triggers> 
  9.                             <Trigger Property="IsInEditMode" Value="True"> 
  10.                                 <Trigger.Setters> 
  11.                                     <Setter TargetName="PART_TabHeader" Property="Visibility" Value="Visible"/> 
  12.                                     <Setter TargetName="PART_TextBlock" Property="Visibility" Value="Collapsed"/> 
  13.                                 </Trigger.Setters> 
  14.                             </Trigger> 
  15.                         </ControlTemplate.Triggers> 
  16.              </ControlTemplate> 
  17.         </Setter.Value> 
  18. </Setter> 

 

接下来,我们需要定义个“EditableTabHeaderControl”类,它具有控制TextBox和TextBlock的能力。如下:

 


  
  1. namespace EditableTabHeaderDemo 
  2.     using System; 
  3.     using System.Windows; 
  4.     using System.Windows.Controls; 
  5.     using System.Windows.Input; 
  6.     using System.Windows.Threading; 
  7.  
  8.     /// <summary> 
  9.     /// Header Editable TabItem 
  10.     /// </summary> 
  11.     [TemplatePart(Name = "PART_TabHeader"Type = typeof(TextBox))] 
  12.     public class EditableTabHeaderControl : ContentControl 
  13.     { 
  14.         /// <summary> 
  15.         /// Dependency property to bind EditMode with XAML Trigger 
  16.         /// </summary> 
  17.         private static readonly DependencyProperty IsInEditModeProperty = DependencyProperty.Register("IsInEditMode", typeof(bool), typeof(EditableTabHeaderControl)); 
  18.         private TextBox textBox; 
  19.         private string oldText; 
  20.         private DispatcherTimer timer; 
  21.         private delegate void FocusTextBox(); 
  22.  
  23.         /// <summary> 
  24.         /// Gets or sets a value indicating whether this instance is in edit mode. 
  25.         /// </summary> 
  26.         public bool IsInEditMode 
  27.         { 
  28.             get 
  29.             { 
  30.                 return (bool)this.GetValue(IsInEditModeProperty); 
  31.             } 
  32.             set 
  33.             {    
  34.                 if (string.IsNullOrEmpty(this.textBox.Text)) 
  35.                 { 
  36.                     thisthis.textBox.Text = this.oldText; 
  37.                 } 
  38.                  
  39.                 thisthis.oldText = this.textBox.Text; 
  40.                 this.SetValue(IsInEditModeProperty, value); 
  41.             } 
  42.         } 
  43.  
  44.         /// <summary> 
  45.         /// When overridden in a derived class, is invoked whenever application code or internal processes call <see cref="M:System.Windows.FrameworkElement.ApplyTemplate"/>
  46.         /// </summary> 
  47.         public override void OnApplyTemplate() 
  48.         { 
  49.             base.OnApplyTemplate(); 
  50.             thisthis.textBox = this.Template.FindName("PART_TabHeader", this) as TextBox; 
  51.             if (this.textBox != null) 
  52.             { 
  53.                 this.timer = new DispatcherTimer(); 
  54.                 this.timer.Tick += TimerTick; 
  55.                 this.timer.Interval = TimeSpan.FromMilliseconds(1); 
  56.                 this.LostFocus += TextBoxLostFocus; 
  57.                 this.textBox.KeyDown += TextBoxKeyDown; 
  58.                 this.MouseDoubleClick += EditableTabHeaderControlMouseDoubleClick; 
  59.             } 
  60.         } 
  61.  
  62.         /// <summary> 
  63.         /// Sets the IsInEdit mode. 
  64.         /// </summary> 
  65.         /// <param name="value">if set to <c>true</c> [value].</param> 
  66.         public void SetEditMode(bool value) 
  67.         { 
  68.             this.IsInEditMode = value
  69.             this.timer.Start(); 
  70.         } 
  71.  
  72.         private void TimerTick(object sender, EventArgs e) 
  73.         { 
  74.             this.timer.Stop(); 
  75.             this.MoveTextBoxInFocus(); 
  76.         } 
  77.  
  78.         private void MoveTextBoxInFocus() 
  79.         { 
  80.             if (this.textBox.CheckAccess()) 
  81.             { 
  82.                 if (!string.IsNullOrEmpty(this.textBox.Text)) 
  83.                 { 
  84.                     this.textBox.CaretIndex = 0
  85.                     this.textBox.Focus(); 
  86.                 } 
  87.             } 
  88.             else 
  89.             { 
  90.                 this.textBox.Dispatcher.BeginInvoke(DispatcherPriority.Render, new FocusTextBox(this.MoveTextBoxInFocus)); 
  91.             } 
  92.         } 
  93.  
  94.         private void TextBoxKeyDown(object sender, KeyEventArgs e) 
  95.         { 
  96.             if (e.Key == Key.Escape) 
  97.             { 
  98.                 this.textBox.Text = oldText
  99.                 this.IsInEditMode = false
  100.             } 
  101.             else if (e.Key == Key.Enter) 
  102.             { 
  103.                 this.IsInEditMode = false
  104.             } 
  105.         } 
  106.  
  107.         private void TextBoxLostFocus(object sender, RoutedEventArgs e) 
  108.         { 
  109.             this.IsInEditMode = false
  110.         } 
  111.  
  112.         private void EditableTabHeaderControlMouseDoubleClick(object sender, MouseButtonEventArgs e) 
  113.         { 
  114.             if (e.LeftButton == MouseButtonState.Pressed) 
  115.             { 
  116.                 this.SetEditMode(true); 
  117.             } 
  118.         } 
  119.     } 
  120. }    

这里有一个问题,当控件进入编辑状态,TextBox变为可见状态时,它不能自动获得focus。一种解决办法是挂一个Timer,每1毫秒轮询一次,检查状态并控制focus。

现在就来添加一个WPF TabControl,并应用ItemContainerStyle。然后双击Header,可以编辑啦~

 


  
  1. <Window x:Class="EditableTabHeaderDemo.MainWindow" 
  2.     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  3.     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
  4.     xmlns:local="clr-namespace:EditableTabHeaderDemo" 
  5.     Title="EditableTabHeaderDemo" Height="300" Width="500"> 
  6.     <Window.Resources> 
  7.         <Style x:Key="EditableTabHeaderControl" TargetType="{x:Type local:EditableTabHeaderControl}"> 
  8.             <!-- The template specified earlier will come here !--> 
  9.         </Style> 
  10.         <Style x:Key="ItemContainerStyle" TargetType="TabItem"> 
  11.             <Setter Property="HeaderTemplate"> 
  12.                 <Setter.Value> 
  13.                     <DataTemplate> 
  14.                         <local:EditableTabHeaderControl 
  15.                    Style="{StaticResource EditableTabHeaderControl}"> 
  16.                             <local:EditableTabHeaderControl.Content> 
  17.                                 <Binding Path="Name" Mode="TwoWay"/> 
  18.                             </local:EditableTabHeaderControl.Content> 
  19.                         </local:EditableTabHeaderControl> 
  20.                     </DataTemplate> 
  21.                 </Setter.Value> 
  22.             </Setter> 
  23.         </Style> 
  24.         <DataTemplate x:Key="ContentTemplate"> 
  25.             <Grid> 
  26.                 <TextBlock HorizontalAlignment="Left" Text="{Binding Name}"/> 
  27.                 <TextBlock HorizontalAlignment="Center" Text="{Binding City}"/> 
  28.             </Grid> 
  29.         </DataTemplate> 
  30.     </Window.Resources> 
  31.     <Grid> 
  32.         <TabControl Grid.Row="0" ItemsSource="{Binding Data}" ItemContainerStyle="{StaticResource ItemContainerStyle}" ContentTemplate="{StaticResource ContentTemplate}" /> 
  33.     </Grid> 
  34. </Window> 

 

许可证

本文以及示例代码文件遵循The Code Project Open License(CPOL)

源码下载

EditableTabHeaderSolution.zip

 

英文链接:Header Editable Tab Control in Wpf

本文转载自:http://powertoolsteam.blog.51cto.com/2369428/469126

葡萄城技术团队

葡萄城技术团队

粉丝 409
博文 587
码字总数 908989
作品 20
西安
高级程序员
私信 提问
WPF中DataTemplate基本原理与缺陷分析

这个文章来源于这样一个问题。下面的两种做 法,在效果上有什么不同?(注:Header是一个自定义DP。) 和 一种是直接在TabItem里放一个TextBox,另一种是通过DataTemplate间接地放进去。这两...

andrewniu
2018/05/30
0
0
【更新】SyntaxEditor发布v2018.1,可共享相同代码库

SyntaxEditor最新版本下载 SyntaxEditor是一款强大的代码语法检验控件,采用了当今最前沿的代码编辑的技术,可以为你代码编辑提供强大的管理功能。最新版支持Visual Studio 2013和Windows 8...

电池盒
01/18
31
0
Microsoft Ribbon for WPF 正式发布

之前写过几篇关于WPF4 中开发Ribbon 工具栏的文章,其中利用的是WPF Ribbon Control 控件库,开发出类似Office 2007 样式的Ribbon 工具栏。当然CodePlex 也提供了Fluent Ribbon Control Sui...

junwong
2012/03/09
871
0
【干货来了】2016年DevExpress资源汇总(示例、视频)

在2016年,著名软件界面解决方案专家DevExpress进行了重大升级,EVGET围绕版本升级推出了一系列干货资源,现将2016年所有Dev示例资源和视频资源汇总于此,欢迎收藏转发点赞哦~ 示例Demo(仍在...

zoujiajun33
2016/12/02
86
0
DevExpress v15.1:WPF控件升级(四)

<下载最新版DevExpress WPF Controls v15.1.5> WPF编辑器 在Token编辑器中的Per-Pixel滚动 水平和垂直的per-pixel滚动 渐进式搜索 查找和组合框编辑器:在只读模式中渐进式搜索。 WPF Tab Co...

Miss_Hello_World
2015/08/27
165
0

没有更多内容

加载失败,请刷新页面

加载更多

Jenkins admin 密码忘记解决

一、admin密码未更改情况 1.进入\Jenkins\secrets目录,打开initialAdminPassword文件,复制密码; find / -name initialAdminPassword [root@jenkins jenkins]# cat /var/lib/jenkins/secre......

SuShine
28分钟前
5
0
LiveData原理分析

LiveData原理分析 1 LiveData简介 大部分Android应用会从网络或SQLite数据库存取数据,并根据数据更新界面。为了避免ANR,主线程中不能存取数据。而后台线程中无法更新界面。通常的做法是让后...

tommwq
42分钟前
4
0
Java描述设计模式(20):命令模式

本文源码:GitHub·点这里 || GitEE·点这里 一、生活场景 1、场景描述 智能电脑的品牌越来越多,由此诞生了一款电脑控制的APP,万能遥控器,用户在使用遥控器的时候,可以切换为自家电视的品...

知了一笑
43分钟前
3
0
java---网络编程(上)

1.1网络编程 网络编程指的是编写运行在多个设备计算机的程序,这些计算机通过网络连接起来 java.net包中提供了两种常见的网络协议的支持: TCP:TCP是传输控制层协议的缩写,它保障了两个应用...

Firefly-
47分钟前
15
0
城市搜索插件 city-query

  今天,给大家介绍一个比较简单有用的插件city-query,大家可以从coding上面下载下来。 git clone https://gitee.com/jflsy/city-query.git   引用插件时只需要src文件下的内容就可以了...

芳缘
52分钟前
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部