[C1] C1ComboBox 的非编辑状态优化
一、前言
先看看 WPF 自带的 ComboBox 在非编辑状态,自定义 ItemTemplate 的情况下,效果如下图所示:

其当前选中的项(红框内)与自定义的 ItemTemplate 一样;
但是 C1ComboBox 的非编辑状态(IsEditable="False"):

总感觉它的非编辑状态并没有完成,虽然数字和英文无法输入,但在红框内依旧可以输入中文文本(QQ拼音输入法的中文输入状态)
;并且在非编辑状态下并非像 Combobox 的非编辑状态可以显示自定义的 ItemTemplate 效果;这篇文章就介绍如何使用 C1ComboBox 模仿 ComboBox 的非编辑状态效果。
二、解决方案
先分析 C1ComboBox 的控件结构:

其中 ComboHeader 部分是由两个控件来回切换显示的,
internal C1TextBoxBase _elementEditControl;
internal ContentPresenter _elementContentControl;
_elementEditControl 则是编辑状态下显示的控件,_elementContentControl 则是非编辑状态下显示的控件(可显示自定义的 ItemTemplate);
而这两个控件转换显示的方法如下(C1TextEditableContentControl):
protected internal void UpdateVisualState()
{
if (this.EditControl == null || this.ContentControl == null)
{
return;
}
if (this.IsInEditMode || this.IsDropDownOpen)
{
this.EditControl.Opacity = 1.0;
this.EditControl.IsTabStop = true;
this.EditControl.IsHitTestVisible = true;
this.ContentControl.Visibility = Visibility.Collapsed;
this.ContentControl.Content = null;
}
else
{
this.EditControl.Opacity = 1.4012984643248171E-45;
this.EditControl.IsTabStop = false;
this.EditControl.IsHitTestVisible = false;
this.ContentControl.Visibility = Visibility.Visible;
this.ContentControl.Content = this.ActualContent;
}
base.Cursor = (this.IsEditable ? Cursors.IBeam : Cursors.Arrow);
}
// 注:EditControl对应_elementEditControl,ContentControl对应_elementContentControl;
即,当 this.IsInEditMode || this.IsDropDownOpen 为 false 时,方可显示自定义的 Itemplate ;
所以,当 ScrollViewer 收缩时(IsDropDownOpen 为 false),设置 ComboHeader 的 IsInEditMode 为 false, 即可保证下拉选择项后,在 ComboHeader 显示自定义的 ItemTemplate;
Loaded += (sender, e) =>
{
C1TextEditableContentControl editBox = GetChildObjects<C1TextEditableContentControl>(cmb, typeof(C1TextEditableContentControl))[0];
cmb.IsDropDownOpenChanged += (sender2, e2) =>
{
editBox.IsInEditMode = false;
};
};
public List<T> GetChildObjects<T>(DependencyObject obj, Type typename) where T : FrameworkElement
{
DependencyObject child = null;
List<T> childList = new List<T>(); for (int i = 0; i <= VisualTreeHelper.GetChildrenCount(obj) - 1; i++)
{
child = VisualTreeHelper.GetChild(obj, i); if (child is T && (((T)child).GetType() == typename))
{
childList.Add((T)child);
}
childList.AddRange(GetChildObjects<T>(child, typename));
}
return childList;
}
GetChildObjects方法
但是,当 ComboHeader 获取焦点,仍然会显示 EditControl ,而不是 ContentControl,所以添加如下代码:
editBox.IsEditable = false;
editBox.GotFocus += (sender2, e2) =>
{
editBox.IsInEditMode = false;
};
需要注意的是,如果不设置 editBox.IsEditable = false; ,点击两次 ComboHeader 还是会进入编辑状态,显示 EditControl 的……
继续但是,当点击 ArrowToggle 按钮展开 ScrollViewer 时,仍旧会显示编辑状态,这个就麻烦了,查看源码可知,该操作时会触发 UpdateSwappedOut 方法以修改 _elementComboHeader 的 ActualContent ,进而触发上面的 UpdateVisualState 方法,而此时 ScrollViewer 的 IsDropDownOpen 属性为 true,导致显示编辑状态,而非自定义的 ItemTemplate;
private void UpdateSwappedOut()
{
if (this._elementComboHeader == null)
{
return;
}
this._elementComboHeader.IsDropDownOpen = this.IsDropDownOpen;
C1ComboBoxItem c1ComboBoxItem = null;
this._isHeaderUpdate = true;
this._elementComboHeader.ActualContent = null;
this._isHeaderUpdate = false;
this._elementComboHeader.UpdateIsWatermarked();
this._elementComboHeader.UpdateVisualState();
if (this.SwappedOutItem != null)
{
this.SwappedOutItem.SwappedOut = false;
this.SwappedOutItem = null;
}
if (this.SelectedItem == null)
{
return;
}
if (this.SelectedIndex != -1)
{
c1ComboBoxItem = (C1ComboBoxItem)base.ItemContainerGenerator.ContainerFromIndex(this.SelectedIndex);
if (c1ComboBoxItem != null && !this.IsDropDownOpen)
{
this.SwappedOutItem = c1ComboBoxItem;
c1ComboBoxItem.SwappedOut = true;
}
}
if (c1ComboBoxItem == null)
{
c1ComboBoxItem = (this.SelectedItem as C1ComboBoxItem);
}
this._isHeaderUpdate = true;
if (c1ComboBoxItem == null)
{
if (base.ItemStringFormat != null && !this.IsEditable && base.ItemTemplate == null)
{
this._elementComboHeader.ActualContent = this.FormattedString(base.ItemStringFormat, this.SelectedItem);
}
else
{
this._elementComboHeader.ActualContent = this.SelectedItem;
}
}
else if (base.ItemStringFormat != null && !this.IsEditable && base.ItemTemplate == null)
{
this._elementComboHeader.ActualContent = this.FormattedString(base.ItemStringFormat, c1ComboBoxItem.Content);
}
else
{
this._elementComboHeader.ActualContent = c1ComboBoxItem.Content;
}
this._isHeaderUpdate = false;
this._elementComboHeader.IsDirty = false;
}
没辙,没找到如何禁止触发 UpdateSwappedOut 方法,或者触发后如何设置 IsDropDownOpen 为 false,所以就把 EditControl 和 ContentControl 两个控件拿出来,再自己写一个 UpdateVisualState 来更新两个状态的转换;
private void UpdateVisualState()
{
if (this.EditControl == null || this.ContentControl == null)
{
return;
}
this.EditControl.Opacity = 1.4012984643248171E-45;
this.EditControl.IsTabStop = false;
this.EditControl.IsHitTestVisible = false;
this.ContentControl.Visibility = Visibility.Visible;
C1ComboBoxItem cmbi = ((C1ComboBoxItem)cmb.ItemContainerGenerator.ContainerFromIndex(cmb.SelectedIndex));
this.ContentControl.Content = cmbi.Content;
base.Cursor = (EditBox.IsEditable ? Cursors.IBeam : Cursors.Arrow);
}
EditControl = GetChildObjects<Control>(cmb, "EditControl")[0];
ContentControl = GetChildObjects<ContentPresenter>(cmb, "ContentControl")[0];
cmb.IsDropDownOpenChanged += (sender2, e2) =>
{
// EditBox.IsInEditMode = false;
UpdateVisualState();
};
public List<T> GetChildObjects<T>(DependencyObject obj, string name) where T : FrameworkElement
{
DependencyObject child = null;
List<T> childList = new List<T>(); for (int i = 0; i <= VisualTreeHelper.GetChildrenCount(obj) - 1; i++)
{
child = VisualTreeHelper.GetChild(obj, i); if (child is T && (((T)child).Name == name | string.IsNullOrEmpty(name)))
{
childList.Add((T)child);
}
childList.AddRange(GetChildObjects<T>(child, name));
}
return childList;
}
一切Over,效果如下:
初始状态:
展开状态:

选择项改变后状态:

[C1] C1ComboBox 的非编辑状态优化的更多相关文章
- odoo14 编辑状态和非编辑状态下隐藏
1 <div class="oe_edit_only"> 2 <a name="remove_group_id" type="obj ...
- cxgrid 非编辑状态下复制当前列的值 真折腾人
1.自带的CTRL +C 只能复制整行,不知是不是版本问题. 2.有分组这个代码就不行了 s:= G1DBView.DataController.Values[G1DBView.Controller. ...
- iOS开发UI篇-tableView在编辑状态下的批量操作(多选)
先看下效果图 直接上代码 #import "MyController.h" @interface MyController () { UIButton *button; } @pr ...
- EasyUI的datagrid获取所有正在编辑状态的行的行编号
今天项目需要用了下EasyUI的datagrid的行编辑功能,跟着API来,只要是将各种状态时的处理逻辑弄好,还是蛮不错的. 开发过程中,遇到了个问题,在编辑完成后我需要获取datagrid所有处于编 ...
- Easyui 设置datagrid 进入编辑状态,保存结束编辑
在datagrid中如何实现让一行进入编辑状态,修改数据后,保存信息呢? //点击列表变成文本框,进入可编辑状态 $(function () { var doc = $(document), tabl ...
- WPF 编辑状态切换
有时候DataGrid编辑的时候一个属性需要根据别的属性呈现不同的编辑状态.这就需要一个做一个状态切换.比如地址是1的时候,读写类型是读写.只读.只写.地址是2的时候,就只读.状态栏切换为TextBo ...
- MVC编辑状态两个DropDownList联动
前几天使用jQuery在MVC应用程序中,实现了<jQuery实现两个DropDownList联动(MVC)>http://www.cnblogs.com/insus/p/3414480. ...
- datagrid combobox事件更新编辑状态下的datagrid行
请问如何从上图状态 点击下拉的combobox中值然后在不取消datagrid编辑状态下更新这一行另一列的数据,达到下图这样的效果: 非常感谢! 给你的combobox 绑定一个onSelect 事 ...
- iOS7 iOS8 UITableviewCell处于编辑状态,dismiss或者back崩溃
今天在项目中遇到一个坑爹的 Crash , 在 iOS7 iOS8 UITableviewCell处于编辑状态,dismiss或者back崩溃 iOS9不会 原因:苹果的BUG代码 解决:在视图消失 ...
随机推荐
- CRL快速开发框架系列教程六(分布式缓存解决方案)
本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...
- 对百度WebUploader开源上传控件的二次封装,精简前端代码(两句代码搞定上传)
前言 首先声明一下,我这个是对WebUploader开源上传控件的二次封装,底层还是WebUploader实现的,只是为了更简洁的使用他而已. 下面先介绍一下WebUploader 简介: WebUp ...
- 代码的坏味道(15)——冗余类(Lazy Class)
坏味道--冗余类(Lazy Class) 特征 理解和维护类总是费时费力的.如果一个类不值得你花费精力,它就应该被删除. 问题原因 也许一个类的初始设计是一个功能完全的类,然而随着代码的变迁,变得没什 ...
- 【uwp】浅谈China Daily 中划词翻译的实现
学习uwp开发也有一段时间了,最近上架了一个小应用(China Daily),现在准备将开发中所学到的一些东西拿出来跟大家分享交流一下. 先给出应用的下载链接:China Daily , 感兴趣的童鞋 ...
- 【转】外部应用和drools-wb6.1集成解决方案
一.手把手教你集成外部应用和drools workbench6.1 1. 首先按照官方文档安装workbench ,我用的是最完整版的jbpm6-console的平台系统,里面既包含j ...
- BPM费控管理解决方案分享
一.方案概述费用是除经营成本外企业的最主要支出,费用管理是财务管理的核心之一,加强企业内控管理如:费用申请.费用报销.费用分摊.费用审批.费用控制和费用支付等,通过科学有效的管理方法规范企业费用管理, ...
- 大数据之Yarn——Capacity调度器概念以及配置
试想一下,你现在所在的公司有一个hadoop的集群.但是A项目组经常做一些定时的BI报表,B项目组则经常使用一些软件做一些临时需求.那么他们肯定会遇到同时提交任务的场景,这个时候到底如何分配资源满足这 ...
- NOIP模板整理计划
先占个坑 [update]noip结束了,弃了 一.图论 1.单源最短路 洛谷P3371 (1)spfa 已加SLF优化 #include <iostream> #include < ...
- BZOJ 3083: 遥远的国度 [树链剖分 DFS序 LCA]
3083: 遥远的国度 Time Limit: 10 Sec Memory Limit: 1280 MBSubmit: 3127 Solved: 795[Submit][Status][Discu ...
- 关于asp.net利用mono部署到Linux上的一些说明
linuxdot.net社区群:102732979(如果你认为你已经在.NET跨平台方面有足够的经验,请参加这个群:103810355). 其中有各种大神,嘿嘿,如果你有问题可以来咨询,完全无偿的免费 ...