如果放置在 Word AddIn 的底部,WPF ComboBox 不会触发 SelectionChanged 事件

WPF ComboBox not firing SelectionChanged event if placed at the bottom of Word AddIn

我正在开发 Office Word AddIn 并将 WPF 控件用于 WinForms UserControl 中的用户界面作为容器(在 ElementHost 控件中)。

我注意到 ComboBox 的问题是,如果将靠近 Word 应用程序底部的项目放置在 AddIn 的底部,它不会触发 SelectionChanged 事件。例如,我可以单击并选择第一个列出的项目(如果幸运的话),否则 ComboBox 下拉列表(弹出窗口)将关闭并且不会触发 SelectionChanged 事件。相反,Word 会执行一些操作,例如缩放或更改页面布局 - 如果插件位于右侧,则这些操作位于 Word 应用程序的右下角。

我找到的唯一解决方法是使用 ComboBox 弹出窗口 'upsided'。在那种情况下,事件发生得很好。正如我所说,这是一种解决方法,我希望看到一些更智能的解决方案。

P.S.:如果我使用的是 WinForms ComboBox 控件,将其放在底部不会导致此问题 - SelectedIndexChanged 事件按预期工作。

谢谢

编辑:我添加了一些非常基本的示例代码。

示例代码:WpfControl.xaml - UI

<UserControl x:Class="WordAddIn.WpfControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="100*"></RowDefinition>
            <RowDefinition Height="40"></RowDefinition>
        </Grid.RowDefinitions>

        <ComboBox x:Name="cboItems" Grid.Row="1" Margin="10,10,10,10"
                  DisplayMemberPath="NAME"
                  SelectionChanged="cboItems_SelectionChanged"/>
    </Grid>
</UserControl>

示例代码:WpfControl.xaml.cs - 代码隐藏

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WordAddIn
{
    /// <summary>
    /// Interaction logic for WpfControl.xaml
    /// </summary>
    public partial class WpfControl : UserControl
    {
        public class Item
        {
            public int ID { get; set; }
            public string NAME { get; set; }
        }

        public WpfControl()
        {
            InitializeComponent();

            List<Item> itemList = new List<Item>();

            for (int i = 1; i < 11; i++)
            {
                itemList.Add(new Item { ID = i, NAME = "Item " + i });
            }

            cboItems.ItemsSource = itemList;
        }

        private void cboItems_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (e.AddedItems != null && e.AddedItems.Count > 0)
            {
                var item = ((object[])(e.AddedItems)).ToList().FirstOrDefault() as Item;

                MessageBox.Show("Item: " + item.NAME + " clicked");

                e.Handled = true;
            }

            e.Handled = false;
        }
    }
}

包含元素宿主的 WpfContrainer 和作为元素宿主子元素的 WpfControl 被添加为插件,点击 Word 功能区的按钮。

示例代码:RibbonWord.cs

private void btnTest_Click(object sender, RibbonControlEventArgs e)
{
    WpfContainer wpfContainer = new WpfContainer();

    var wpfContainerPane = Globals.ThisAddIn.CustomTaskPanes.Add(wpfContainer, "AddIn");

    wpfContainerPane.Visible = true;
}

我遇到了同样的问题。当下拉列表位于 wpf 外部时,SelectionChanged 不起作用。尝试以这种方式更改您的代码

Xaml:

   <ComboBox x:Name="cboItems" 
             Grid.Row="1" 
             Margin="10,10,10,10"
             DisplayMemberPath="NAME"
             SelectionChanged="cboItems_SelectionChanged"
             DropDownOpened="ComboBox_OnDropDownOpened"
             DropDownClosed="ComboBox_OnDropDownClosed" />

后面的代码:

namespace WordAddIn
{        
    public partial class WpfControl : UserControl
    {
        // your code

        private DispatcherFrame dispatcherFrame;           

        private object DispatcherOperationBegin(object arg)
        {
            dispatcherFrame = new DispatcherFrame();
            Dispatcher.PushFrame(dispatcherFrame);
            return null;
        }

        private void ComboBox_OnDropDownOpened(object sender, EventArgs e)
        {
            Dispatcher.BeginInvoke(DispatcherPriority.Normal, new DispatcherOperationCallback(DispatcherOperationBegin), null);
        }

        private void ComboBox_OnDropDownClosed(object sender, EventArgs e)
        {
            dispatcherFrame.Continue = false;
        }
    }
}

有关 DispatcherFrame 的更多信息,您可以找到 here.