Excel VSTO插件中如何正确操作ElementHost托管的WPF控件?
解决Excel VSTO插件中WPF TabControl属性无法修改的问题
我正在开发Excel VSTO插件,想要使用WPF控件,参考相关官方教程后添加了TabControl做测试。需求是点击Ribbon按钮时,根据条件以编程方式切换TabItem并修改其属性,但最初只能访问TabItem的Header文本,无法修改Header或设置IsSelected属性。
最初的错误代码
VB代码
Imports Microsoft.Office.Tools Imports Microsoft.Office.Tools.Ribbon Public Class Ribbon1 Private myUserControl1 As MyUserControl Private myCustomTaskPane As CustomTaskPane Private Sub btnCheck_Click(sender As Object, e As RibbonControlEventArgs) Handles btnCheck.Click ' Show the taskpane myUserControl1 = New MyUserControl myCustomTaskPane = Globals.ThisAddIn.CustomTaskPanes.Add(myUserControl1, "Test addin") myCustomTaskPane.Width = 500 myCustomTaskPane.Visible = True Dim uc As New UserControl1 ' Check if there's a table If isThereATable() Then MsgBox("There is") MsgBox(uc.Tab2.Header) ' works uc.Tab2.Header = "new header" ' does not work Else MsgBox("There is not") End If End Sub End Class
对应的WPF XAML代码
<UserControl x:Class="UserControl1" 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" xmlns:local="clr-namespace:AutoTable" mc:Ignorable="d" d:DesignHeight="450" Width="500"> <Grid Width="500"> <TabControl BorderThickness="1" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" HorizontalAlignment="Left" Width="500" Name="MainTab"> <TabItem Header="Init" Name="Tab1" > <Grid Background="#FFE5E5E5" Margin="0"> <TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" Text="The following button should create a table." VerticalAlignment="Top" FontSize="16" Margin="10,10,0,0"/> <Button Content="Create table" HorizontalAlignment="Left" Margin="5,60,0,0" VerticalAlignment="Top" Width="100" Click="Button_Click" Height="30" FontSize="14"/> </Grid> </TabItem> <TabItem Header="CC" Name="Tab2" > <Grid Background="#FFE5E5E5"/> </TabItem> </TabControl> </Grid> </UserControl>
问题原因与解决方法
核心问题
- 控件托管要求:Excel VSTO的CustomTaskPane仅支持托管Windows Forms控件,WPF用户控件必须嵌套在Windows Forms用户控件中才能被正确加载。
- 实例引用错误:最初代码中初始化了新的
UserControl1实例uc,但修改的是这个未加载到界面的实例属性,而非已经添加到任务窗格的那个实例,导致界面无变化。
修正后的代码
Public Class Ribbon1 Private ThisUserControl As UserControlWF Private ThisTaskPane As Microsoft.Office.Tools.CustomTaskPane Private Sub ShowTaskPane_Click(sender As Object, e As RibbonControlEventArgs) Handles ShowTaskPane.Click ThisUserControl = New UserControlWF ' CustomTaskPanes只能添加Windows Forms UI元素,直接添加WPF控件会报错 ThisTaskPane = Globals.ThisAddIn.CustomTaskPanes.Add(ThisUserControl, "Title") ThisTaskPane.Width = 510 ThisTaskPane.Visible = True ' 加载任务窗格后根据条件修改控件属性 If isThereATable() Then MsgBox("There is a table") ' 修改已加载到界面的WPF控件实例属性 ThisUserControl.UserControlWPF1.Tab2.Header = "Different Header" ' 原Header为"TabItem2" ThisUserControl.UserControlWPF1.Tab2.IsSelected = True ' 默认选中Tab1 ' 错误做法:初始化新实例而非操作已加载的实例 ' Dim uc As New UserControlWPF ' MsgBox(uc.Tab2.Header) ' 能读取类默认属性 ' uc.Tab2.Header = "Different Header" ' 修改的是未加载的实例,界面无变化 Else MsgBox("There is no table") End If End Sub End Class
内容的提问来源于stack exchange,提问作者Edgar O.
相关产品推荐
相关产品推荐

