Jer*_*son 10 .net c# excel vsto datetimepicker
在这里记录了微软的问题 - 可以下载Repro:https://connect.microsoft.com/VisualStudio/feedback/details/741454/value-change-event-doesnt-fire-for-datetimepicker-controls-used-在-VSTO-插件
如果将DateTimePicker放在Excel VSTO浮动加载项中并在日历下拉时将其定位,则它位于加载项的边缘之外,请参见此处:

选择绿色中圈出的任何日期按预期工作,但点击任何以红色圈出的日期时,它只会关闭日历下拉菜单并且不会设置日期!
有谁知道我怎么解决这个问题?
编辑
这个SO用户使用WPF遇到了这个问题: VSTO WPF ContextMenu.MenuItem在没有引发的TaskPane外部单击

该问题的答案显示该问题已被报道连接一段时间但仍然没有VSTO 4.0 SP1的解决方案:https://connect.microsoft.com/VisualStudio/feedback/details/432998/excel-2007-vsto-custom-任务窗格与- WPF的上下文菜单具有焦点,问题
其中一个解决方法是使用DispatcherFrame来为消息添加消息并为菜单订阅GotFocusEvent和LostFocusEvent.http://blogs.msdn.com/b/vsod/archive/2009/12/16/excel-2007-wpf-events-are-not-fired-for-items-that-overlap-excel-ui-for- wpf-context-menus.aspx但这是菜单的所有WPF代码,而不是Winform DateTimePicker的解决方案.
Repro for Microsoft Connect:
使用TaskPane的新项目> Excel 2010加载项; 使用Microsoft.Office.Core;
namespace ExcelAddIn2 {public partial class ThisAddIn {TaskPaneView MyTaskView = null; Microsoft.Office.Tools.CustomTaskPane MyTaskPane = null;
using TaskPane;
using Microsoft.Office.Core;
namespace ExcelAddIn2
{
public partial class ThisAddIn
{
TaskPaneView MyTaskView = null;
Microsoft.Office.Tools.CustomTaskPane MyTaskPane = null;
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
//setup custom taskpane
MyTaskView = new TaskPaneView();
MyTaskView.currentInstance = Globals.ThisAddIn.Application;
MyTaskPane = this.CustomTaskPanes.Add(MyTaskView, "MyTaskView");
MyTaskPane.DockPosition = Microsoft.Office.Core.MsoCTPDockPosition.msoCTPDockPositionFloating;
MyTaskPane.DockPositionRestrict = MsoCTPDockPositionRestrict.msoCTPDockPositionRestrictNoChange;
MyTaskPane.Visible = true;
}
}
Run Code Online (Sandbox Code Playgroud)
文件菜单>添加>新建项目>类库>命名为TaskPane
然后在TaskPane项目中创建一个名为TaskPaneView的用户控件
public partial class TaskPaneView : UserControl
{
public TaskPaneView()
{
InitializeComponent();
}
public Microsoft.Office.Interop.Excel.Application currentInstance { get; set; }
public TaskPaneCtrl getTaskPaneCtrl
{
get { return this.taskPaneCtrl1; }
}
}
Run Code Online (Sandbox Code Playgroud)
接下来,使用DateTimePicker创建用户控件,确保Calendar控件位于用户控件的右下角
public partial class TaskPaneCtrl : UserControl
{
public TaskPaneCtrl()
{
InitializeComponent();
}
}
Run Code Online (Sandbox Code Playgroud)
在TaskPane类库中引用Excel Interop(例如c:\ Program Files x86\Microsoft Visual Studio 14.0\Visual Studio Tools for Office\PIA\Office14\Microsoft.Office.Interop.Excel.dll).
构建解决方案.评论不起作用的部分.构建解决方案
现在将TaskPaneCtrl拖放到TaskPaneView上并取消注释无法编译的内容.
F5并单击日历控件,现在尝试选择任务窗格区域之外的日期.没有Value Change事件触发,它表现得像日历外的点击!
注意:我尝试了一个不受控制的下拉列表,但它的事件发生了火灾!
"浮动"是这里问题的关键.从来没有问题的是,您依靠Excel中的消息泵来分派Windows消息,使这些控件响应输入的消息.WPF和Winforms一样出错,它们有自己的调度循环,在消息传递到窗口之前过滤消息.不使用各自调度员时出现问题的关键事项是标签和快捷键击等.
然后有些人会在调度消息之前通过Excel进行自己的过滤来引发这种问题.我猜一个反恶意软件的功能,微软永远担心乱搞Office应用程序.
Winforms解决方案与WPF解决方法相同,您需要自己的消息循环.这需要一些手术,DateTimePicker不会合作,因为它不允许取消DropDown事件,并且在日历已经显示之后引发它.解决方法很愚蠢但有效,在表单上添加一个按钮,看起来就像DTP上的下拉箭头,并使其与箭头重叠,以便点击而不是箭头.
使按钮与下拉箭头重叠的一些示例代码:
public Form1() {
InitializeComponent();
var btn = new Button();
btn.BackgroundImage = Properties.Resources.DropdownArrow;
btn.FlatStyle = FlatStyle.Flat;
btn.BackColor = Color.FromKnownColor(KnownColor.Window);
btn.Parent = dateTimePicker1;
btn.Dock = DockStyle.Right;
btn.Click += showMonthCalendar;
dateTimePicker1.Resize += delegate {
btn.Width = btn.Height = dateTimePicker1.ClientSize.Height;
};
}
Run Code Online (Sandbox Code Playgroud)
Click事件处理程序需要显示包含MonthCalendar的对话框:
private void showMonthCalendar(object sender, EventArgs e) {
dateTimePicker1.Focus();
using (var dlg = new CalendarForm()) {
dlg.DateSelected += new DateRangeEventHandler((s, ea) => dateTimePicker1.Value = ea.Start);
dlg.Location = dateTimePicker1.PointToScreen(new Point(0, dateTimePicker1.Height));
dlg.ShowDialog(this);
}
}
Run Code Online (Sandbox Code Playgroud)
使用CalendarForm,您可以添加无边界的表单,并且只包含MonthCalendar:
public partial class CalendarForm : Form {
public event DateRangeEventHandler DateSelected;
public CalendarForm() {
InitializeComponent();
this.StartPosition = FormStartPosition.Manual;
monthCalendar1.Resize += delegate {
this.ClientSize = monthCalendar1.Size;
};
monthCalendar1.DateSelected += monthCalendar1_DateSelected;
}
void monthCalendar1_DateSelected(object sender, DateRangeEventArgs e) {
if (DateSelected != null) DateSelected(this, e);
this.DialogResult = DialogResult.OK;
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1820 次 |
| 最近记录: |