WPF风格的下拉框,带有两列内容。

7

我已经查找到一些内容,但目前在具有两个列的组合框中卡住了。我有可用的xaml主题,组合框“样式”已定义并且像预期的那样正常工作,因此这部分是可以的。

现在,我需要一个组合框来显示两个值,可以将其视为显示下拉列表中的州缩写和州名称,这些值来自于DataTable.DefaultView绑定源。

如果我有

<my:cboStates TextSearch.TextPath="StateAbbrev">
  <ComboBox.ItemTemplate>
    <DataTemplate>
      <StackPanel Orientation="Horizontal" TextSearch.Text="{Binding Path=StateAbbrev}">
        <TextBlock Text="{Binding Path=StateAbbrev}"/>
        <TextBlock Text="{Binding Path=FullStateName}" Margin="10 0"/>
      </StackPanel>
    </DataTemplate>
  </ComboBox.ItemTemplate>
</my:cboStates>

这个可以正常工作。 现在,我的困境是...我想在5个不同的表单上使用相同的功能,并且所有的内容都显示相同,如果有变化(不是这个,而是其他多列组合框),我不想直接将其放到表单的XAML文件中。
我希望将其放入主题的资源字典文件中,然后一遍又一遍地重复使用那个“样式”。 这是有道理的。 但是,当我这样做时,如果绑定到数据表,则只得到以下结果,尝试将其作为样式:下拉菜单显示的值为

System.Data.DataRowView
System.Data.DataRowView
System.Data.DataRowView
System.Data.DataRowView

而不是实际的两列。 这是我在“主题”资源字典中拥有的内容。

<DataTemplate x:Key="myStateComboTemplate" >
  <StackPanel Orientation="Horizontal"  >
    <TextBlock Text="{Binding Path=StateAbbrev}"/>
    <TextBlock Text="{Binding Path=FullStateName}"/>
  </StackPanel>
</DataTemplate>

<Style x:Key="StyleMyStatesCombobox" TargetType="{x:Type ComboBox}" 
  BasedOn="{StaticResource MyOtherWorkingComboBoxStyle}" >
  <Setter Property="TextSearch.TextPath" Value="{Binding Path=StateAbbrev}" />
  <Setter Property="ItemTemplate" Value="{StaticResource myStateComboTemplate}" />
</Style>

如果我在表单上创建了两个 "cboStates" 类的实例,并将其中一个设置为首先列出的显式样式,第二个基于 "Style" 设置,那么第二个将失败,仅显示重复的 System.Data.DataRowView 条目,而不是实际的数据内容。

我错过了什么?

因此,为了澄清我的要求...

状态... ex data

AL Alabama
AK Alaska
AZ Arizona
AR Arkansas
CA California
CO Colorado
CT Connecticut
DE Delaware

我希望下拉列表框能显示缩写的州名,例如:AL、AK、AZ等,并且这个下拉列表框应该更窄。这也将是“SelectedValue”返回的值。
实际的下拉列表将会按照上述列出的方式呈现数据,同时显示州的缩写和全名。
所需下拉列表框的示例如下图所示: enter image description here

有什么原因不能将它们连接在一起吗?我在想你可以尝试使用元组,但不确定会怎样工作。 - Bob.
@Bob,我考虑过元组,但这只是一个简化的例子,任何人都能理解。实际上,我将有许多类似的组合框,它们将具有来自表格的数据,并且可能会变化,因此不是固定值。我不想查询数据库,然后循环遍历并将其放入另一个存储元组中,以便根据所需从结果组合框呈现重新解析键/值/替代值/额外键等。 - DRapp
那么 Dictionary<string, string> 呢?将 Key 绑定到一个 TextBlock,将 Value 绑定到另一个 TextBlock?或者可能有超过两行的情况吗? - Bob.
你能发布MyOtherWorkingComboBoxStyle资源的标记吗? - Jf Beaulac
1个回答

1

终于搞定了...对于那些尝试类似操作的人来说,由于我想要一个可以在整个应用程序中使用的标准“class”实例,但又不想在每个页面中显式地硬编码引用XAML,因此部分样式必须在实际的代码类实例中处理。

由于我不确定.NET框架何时构建所有控件、样式分配等,所以当直接从XAML中获取时它能够正常工作,但是在代码中却失败了,这让我感到沮丧。因此,我最终在代码中强制指定了项目模板和TextSearch.TextPath值。以下是该类的简短片段:

public class myStatesCombo : ComboBox
{
   public myStatesCombo()
   {
      Loaded += myAfterLoaded;
   }

   protected static DataTable myTableOfStates;

   public void myAfterLoaded()
   {
      if( myTableOfStates == null )
        myTableOfStates = new DataTable();

      CallProcedureToPopulateStates( myTableOfStates );

      ItemsSource = myTableOfStates.DefaultView;

      // AFTER the object is created, and all default styles attempted to be set,
      // FORCE looking for the resource of the "DataTemplate" in the themes.xaml file
      object tryFindObj = TryFindResource("myStateComboTemplate" );
      if( tryFindObj is DataTemplate )
         ItemTemplate = (DataTemplate)tryFindObj;

      // NOW, the CRITICAL component missed in the source code
      TextSearch.SetTextPath( this, "StateAbbrev" );
   }
}

现在,特别注意一下。在我用来填充DataTable的例程中,我会预先检查表是否存在。第一次进入时,我会创建表。如果我需要重新填充它,如果每次都只是做一个“new DataTable”,那么它就会清除数据/项模板绑定。为了防止这种情况发生,我会这样做:
if( myTableOfStates.Rows.Count > 0 )
  myTableOfStates.Rows.Clear();

接下来,我调用我的Sqlexecute调用从数据库查询(DataAdapter)并填充(datatable)。

现在,所有的数据似乎都被正确地填充了,绑定显示和文本搜索已经完成,准备就绪。


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