如何让Microsoft.VisualStudio.Diagnostics.UI.Controls.MultiSelectComboBox工作。

10

我试图实现的目标:

我正在开发一个Visual Studio插件,需要使用MultiSelectComboBox。为了与VisualStudio的外观和感觉相匹配,我决定使用它们自己的类:

public class MultiSelectComboBox : UserControl, IComponentConnector, IStyleConnector
Name: Microsoft.VisualStudio.Diagnostics.UI.Controls.MultiSelectComboBox
Assembly: Microsoft.VisualStudio.Diagnostics.Common, Version=12.0.0.0

微软在他们的代码分析页面中使用了这个类:查看/其他窗口/代码分析

问题:

当我想要使用它时,它显然不能正常工作。 :)

以下是我如何使用它的示例代码:

public TestClass()
{
    InitializeComponent();
    multiSelectComboBox.ItemsSource = new string[] { "Item 1", "Item 2", "Item 3" };
    multiSelectComboBox.AllItemsText = "All items";
}

这里是XAML标记:

<UserControl ...
    xmlns:vsUiControls="clr-namespace:Microsoft.VisualStudio.Diagnostics.UI.Controls;assembly=Microsoft.VisualStudio.Diagnostics.Common"
    ...>
    <vsUiControls:MultiSelectComboBox x:Name="multiSelectComboBox"/>
</UserControl>

现在,MultiSelectComboBox已经出现了,您可以与它进行交互,但是当您选择一些项目而不是全部时,这些项目应该显示为这样:Item 1; Item 3(假设您选择了除Item 2之外的所有项目)。然而,显示的文本只是Item 1Item 3,完全缺少分隔符。

有趣的是(我忽视了很长时间),如果您调试代码并请求multiSelectComboBox.SelectedItemsText,它会返回带有分号分隔的正确值。

因此,问题是,如果值存储正确,为什么在我使用代码时无法正确显示它,但在Microsoft的Code Analysis页面上使用时是正确的?

描述MultiSelectComboBox style的XAML标记仅包含一个SelectedItemsText实例,这是一个绑定。请参见下面从.Net Reflector中获取的内容:

<local:MultiSelectComboBox
    p1:UserControl.Name="_this"
    p1:AutomationProperties.Name="{Binding RelativeSource={RelativeSource Self},Path=AllItemsText}"
    xmlns:p1="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:local="clr-namespace:Microsoft.VisualStudio.Diagnostics.UI.Controls;assembly=Microsoft.VisualStudio.Diagnostics.Common,Version=12.0.0.0,Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a">
    ...
    <Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
        <local:CheckComboBox
            CheckComboBox.Name="_comboBox"
            p4:FrameworkElement.Style="{StaticResource ComboStyle}"
            p4:Control.HorizontalContentAlignment="Stretch"
            p4:KeyboardNavigation.DirectionalNavigation="Continue"
            p4:AutomationProperties.Name="{Binding ElementName=_this,Path=SelectedItemsText,Mode=OneWay}"
            xmlns:p4="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
            <ItemsControl.ItemTemplate>
                ...
            </ItemsControl.ItemTemplate>
        </local:CheckComboBox>
    </Grid>
</local:MultiSelectComboBox>

我不确定为什么SelectedItemsText绑定到AutomationProperties.Name(已附加?)属性,但这是.Net Reflector给我的。如果我调试我的代码,我可以在MultiSelectComboBox中的CheckedComboxBox控件的Name属性中找到分号分隔的值。

这些值似乎被正确存储,绑定似乎也起作用,但是显示在UI上的文本不包含分隔符。我只是感到困惑...

1个回答

2

我查看了反编译的源代码,发现属性SelectedItemsText仅用于UI自动化(附加属性AutomationProperties.Name)。真正的显示文本是通过以下XAML显示的:

<TextBlock Name="PART_SummaryPartialSelection" Grid.Row="0" Style="{StaticResource DropDownTextBlockStyle}" Visibility="{Binding Path=AllItemsSelected, ElementName=_this, Converter={StaticResource booleanToVisibilityConverterNegative}}">
  <ItemsControl Name="PART_Items" Focusable="False" Background="#00FFFFFF" IsHitTestVisible="False" x:Uid="M113" ItemsSource="{Binding SelectedItems, ElementName=_this}" ItemTemplate="{Binding DisplayAreaTemplate, ElementName=_this}">
    <ItemsControl.ItemsPanel>
      <ItemsPanelTemplate x:Uid="M115">
        <StackPanel IsItemsHost="True" Orientation="Horizontal" x:Uid="M116" />
    </ItemsPanelTemplate>
  </ItemsControl.ItemsPanel>
  </ItemsControl>
</TextBlock>

所以它只是一个水平的StackPanel,其中的项一个接一个地排列,没有任何分隔符。因此,您需要修改此模板或仅在项目中添加分号(看起来Visual Studio是这样做的,因为它甚至在最后一个项目之后显示分号 - item1; item2;)。


谢谢Nikolay指出XAML中这个重要的部分。我会仔细看一下,并考虑如何让它正常工作。 - Shakaron
他们实际上做的与您预测的几乎相同,但是他们没有在每个文本后添加分号,而是将3个元素放入堆栈面板(Item 1、Item 2、Item 3)。所有元素都包含2个部分:第一个是TextBlock,其中包含项目的文本表示(例如"Item 1"),第二个部分也是TextBlock,但它只包含一个分号。因此,在堆栈面板上有3个这样的元素。 - Shakaron
但是他们必须做很多事情,因为在静态分析中括号中有一个计数器,当他们将事物串在“PART_SummaryPartialSelection”中时,该计数器被删除。所以现在事情开始变得丑陋、混乱和困难。 - Shakaron
我没有将你的答案标记为解决方案,尽管它非常有帮助,但我仍然没有可用的代码。 :( - Shakaron

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接