2012-05-10 21 views
9

Logged vấn đề với Microsoft ở đây - Repro hiện có sẵn để tải về: https://connect.microsoft.com/VisualStudio/feedback/details/741454/value-change-event-doesnt-fire-for-datetimepicker-controls-used-in-vsto-add-insBUG: Cant chọn ngày trên DatePicker nằm ngoài một nổi VSTO Add-In

Nếu bạn đặt một DateTimePicker trong một VSTO Excel thả nổi Thêm -Trong và định vị nó như vậy khi lịch giảm xuống, nó nằm ngoài rìa của add-in, xem tại đây:

enter image description here

Chọn bất kỳ ngày vòng quanh trong các công trình xanh như mong đợi, nhưng khi nhấp vào bất kỳ ngày nào được khoanh tròn bằng màu đỏ, nó chỉ đóng cửa sổ thả xuống lịch và không đặt ngày!

Có ai biết cách khắc phục sự cố này không?

EDIT

dùng SO này đã gặp phải sự cố sử dụng WPF: VSTO WPF ContextMenu.MenuItem Click outside a TaskPane not raised

enter image description here

Câu trả lời cho câu hỏi đó cho thấy vấn đề này đã được báo cáo để kết nối một khi trở lại nhưng vẫn không có giải pháp với VSTO 4.0 SP1: https://connect.microsoft.com/VisualStudio/feedback/details/432998/excel-2007-vsto-custom-task-pane-with-wpf-context-menu-has-focus-problems

Một trong những cách giải quyết là sử dụng DispatcherFrame để bơm tin nhắn và đăng ký GotFocusEvent và LostFocusEvent cho menu. 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 nhưng đây là tất cả mã WPF cho trình đơn không phải là giải pháp cho Winform DateTimePicker.

Repro cho Microsoft Connect:

New Project> Excel 2010 Add-In

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; 
} 

Menu File> Add> New Project> Class Library> đặt tên taskpane

Sau đó, trong Dự án TaskPane tạo Điều khiển người dùng được gọi là 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; } 
    } 

} 

Tiếp theo, tạo một User Control với một DateTimePicker, đảm bảo sự kiểm soát Lịch nằm về phía góc dưới bên phải của điều khiển người dùng

public partial class TaskPaneCtrl : UserControl 
{ 
public TaskPaneCtrl() 
{ 
    InitializeComponent(); 
} 
} 

F5 và nhấp vào Lịch kiểm soát, bây giờ cố gắng chọn một ngày đó là ngoài khu vực nhiệm vụ. Không có sự kiện Thay đổi giá trị nào kích hoạt, nó hoạt động giống như một cú nhấp chuột bên ngoài lịch!

Lưu ý: Tôi đã thử một danh sách thả xuống rơi khỏi tầm kiểm soát nhưng các sự kiện của nó CHÁY!

Trả lời

7

"Nổi" là chìa khóa cho vấn đề ở đây. Điều không bao giờ là vấn đề là bạn dựa vào máy bơm thông báo trong Excel để gửi các tin nhắn Windows, các thông điệp mà làm cho các điều khiển này đáp ứng với đầu vào. Điều này đi sai trong WPF nhiều như Winforms, họ có vòng lặp công văn riêng của họ để lọc các thông báo trước khi chúng được gửi đến cửa sổ. Những điều quan trọng xảy ra khi người điều phối tương ứng của họ không được sử dụng là những thứ như tabbing và tổ hợp phím ngắn.

Và sau đó một số, loại vấn đề này sẽ được gây ra bởi Excel thực hiện lọc riêng của mình trước khi gửi thư. Tôi đoán tại một tính năng chống phần mềm độc hại, Microsoft luôn lo lắng về các chương trình gây rối với các ứng dụng Office.

Giải pháp Winforms giống như giải pháp WPF, bạn cần phải bơm vòng lặp tin nhắn của riêng bạn. Điều đó đòi hỏi một số phẫu thuật, DateTimePicker sẽ không hợp tác vì nó không cho phép sự kiện DropDown của nó bị hủy bỏ và nó được nâng lên sau lịch đã được hiển thị. Cách giải quyết là ngớ ngẩn nhưng hiệu quả, thêm một nút vào biểu mẫu của bạn trông giống như mũi tên thả xuống trên DTP và làm cho nó chồng lên mũi tên để nó được nhấp thay vì mũi tên.

Một số mã ví dụ cho nhận nút để chồng chéo mũi tên sổ xuống:

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; 
     }; 
    } 

Việc xử lý sự kiện Click cần để hiển thị một hộp thoại có chứa một 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); 
     } 
    } 

Với CalendarForm một mẫu bạn thêm đường viền không có viền và chỉ chứa 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; 
    } 
} 
+1

+1 Brilliant! Đọc như một SOX (Visual KB?), Nếu điều này làm việc khi tôi thử nó vào thứ hai, không có từ nào có thể bày tỏ lòng biết ơn của tôi. –

+1

mức độ tuyệt vời exceeeded. tốt đẹp một Hans –

2

suy đoán:
Lỗi xảy ra vì bề mặt của datetimepicker không được hiển thị cho đến sau khi thông báo nhấp được gửi.

Các bước tiếp theo để trả lời:
Nếu có sẵn thử kiểm tra với một số điều khiển bộ chọn ngày giờ của bên thứ 3. Tôi nhận ra đây không phải là câu trả lời hoàn chỉnh vì tôi chưa biết liệu nó có khắc phục được sự cố của bạn hay không.

Câu trả lời có thể khác: Thay đổi kích thước của thanh tác vụ để vừa với điều khiển. Điều này sẽ phân loại lỗi, nhưng trông hơi lạ từ một quan điểm của người dùng.