【问题标题】:Getting value of TextBlock inside ComboBox DataTemplate在 ComboBox DataTemplate 中获取 TextBlock 的值
【发布时间】:2010-08-09 14:55:48
【问题描述】:

我有以下 XAML:

<ComboBox Height="23" HorizontalAlignment="Left" Grid.Row="6" Grid.Column="2"
          Name="cbo_team" VerticalAlignment="Top" Width="148"
          DataContext="{Binding ElementName=cbo_component, Path=SelectedItem}"
          SelectedIndex="0">
    <ComboBox.ItemsSource>
        <Binding XPath="Teams/Team/@id"
                 Converter="{StaticResource xmlConverter}">
            <Binding.ConverterParameter>
                <local:XmlConverterParameter
                    XPathTemplate="/Products/Teams/Team[{0}]"
                    XPathCondition="@id='{0}'" />
            </Binding.ConverterParameter>
        </Binding>
    </ComboBox.ItemsSource>
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding XPath=@name}" />
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

在 C# 中,我试图获取 TextBlock 的值,该值位于 ComboBox 的当前选定项中。我怎么做? This question 几乎相同,但唯一的答案没有帮助。

【问题讨论】:

    标签: c# wpf combobox datatemplate textblock


    【解决方案1】:

    查看此示例。文本块(组合框下方)显示组合框中当前选定 xml 元素的名称属性值。将弹出一个消息框,其中包含在可视树中查找的相同结果。初始选择更改时查找失败。看起来组合框项是在设置所选项目后创建的。

    XAML:

    <Window x:Class="CBTest.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Height="300" Width="300">
    
        <Window.Resources>
            <XmlDataProvider x:Key="UsersData" XPath="Users">
                <x:XData>
                    <Users xmlns="">
                        <User name="Sally" />
                        <User name="Lucy" />
                        <User name="Linus" />
                        <User name="Charlie" />
                    </Users>
                </x:XData>
            </XmlDataProvider>
        </Window.Resources>
    
        <StackPanel>
    
            <ComboBox 
                Name="_comboBox"
                ItemsSource="{Binding Source={StaticResource UsersData},XPath=*}"
                SelectedIndex="0"
                SelectionChanged="OnComboBoxSelectionChanged">
                <ComboBox.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding XPath=@name}" Name="nameTextBlock" />
                    </DataTemplate>
                </ComboBox.ItemTemplate>
            </ComboBox>
    
            <!-- Below shows how to get the value of selected item directly from the data. -->
            <TextBlock 
                DataContext="{Binding Path=SelectedItem, ElementName=_comboBox}"
                Text="{Binding XPath=@name}" />
    
        </StackPanel>
    
    </Window>
    

    后面的代码,展示了如何通过遍历可视化树直接获取文本:

    private void OnComboBoxSelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        ComboBox comboBox = sender as ComboBox;
        ComboBoxItem comboBoxItem = comboBox.ItemContainerGenerator.ContainerFromItem(comboBox.SelectedItem) as ComboBoxItem;
        if (comboBoxItem == null)
        {
            return;
        }
        TextBlock textBlock = FindVisualChildByName<TextBlock>(comboBoxItem, "nameTextBlock");
        MessageBox.Show(textBlock.Text);
    }
    
    private static T FindVisualChildByName<T>(DependencyObject parent, string name) where T : DependencyObject
    {
        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
        {
            var child = VisualTreeHelper.GetChild(parent, i);
            string controlName = child.GetValue(NameProperty) as string;
            if (controlName == name)
            {
                return child as T;
            }
            T result = FindVisualChildByName<T>(child, name);
            if (result != null)
                return result;
        }
        return null;
    }
    

    【讨论】:

    • 在 ComboBox 中有一个显示所选项目内容的辅助字段似乎是一种不必要的解决方法,只是为了能够在 C# 中读取该辅助字段。不过,我会记住这一点,这是一种丑陋的 hack。
    • 我刚刚在示例中添加了该文本块,以向您展示如何从所选项目中获取名称属性。不需要文本块。您是否将其与组合框项目的数据模板中使用的文本块混淆了?
    • 哦,明白了。当我检查 C# 中的 SelectedItem 属性时,我得到了一个 XML 结构。我可以检查那里的Attributes 属性并在C# 中提取name 属性的值,但这似乎是多余的,因为name 属性已经在XAML 中提取——这就是TextBlock 中显示的内容.似乎我应该能够从ComboBox 中提取一个简单的字符串值——TextBlock 中显示的name 属性——而不必担心该值来自的 XML 结构。
    • 问题是您没有对所选组合框项目的文本块的引用。您需要使用后面的代码在可视化树中搜索它。我编辑了我的答案以展示这种(不太优雅)的方法。
    • 一个人需要成为使用微软技术的策划者。我的智商很低,是时候切换到开源了。
    【解决方案2】:

    抱歉,聚会晚了一点 :),但以下方法也有效(讽刺的是,与您的修复方法相同!)

    TextBlock tb1 = (TextBlock)cbo_team.SelectedItem;
    MessageBox.Show(tb1.Text);
    

    【讨论】:

      【解决方案3】:
      private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
      {
          ListBox ContactListBox = sender as ListBox;
          ListBoxItem listBoxItem = ContactListBox .ItemContainerGenerator.ContainerFromItem(ContactListBox.SelectedItem) as ListBoxItem;
          if (listBoxItem == null)
          {
              return;
          }
          TextBlock txtBlock = FindVisualChildByName<TextBlock>(listBoxItem, "ListTextBlock");
         MessageBox.Show(txtBlock.Text);                        
      }
      
      private static T FindVisualChildByName<T>(DependencyObject parent, string name) where T : DependencyObject
      {
          for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
          {
              var child = VisualTreeHelper.GetChild(parent, i);
              string controlName = child.GetValue(NameProperty) as string;
              if (controlName == name)
              {
                  return child as T;
              }
              T result = FindVisualChildByName<T>(child, name);
              if (result != null)
                  return result;
          }
          return null;
      }
      

      【讨论】:

        【解决方案4】:

        其他人已经建议使用 SelectionChanged 事件。下面的代码没有测试,你可以试一试。

        private void OnMyComboBoxChanged(object sender, SelectionChangedEventArgs e)
        {
            TextBlock tvContent = (sender as ComboBox).SelectedItem as TextBlock;
        
            string content = tvContent.Text;
        }
        

        【讨论】:

          猜你喜欢
          • 2021-11-16
          • 2011-10-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-10-04
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多