在ComboBox

时间:2016-06-17 19:40:52

标签: c# wpf combobox itemsource

这是在我的app.xaml文件中(缩减):

<Application.Resources>
    <x:Array x:Key="SongTitleString" Type="local:ComboBoxItemString">
        <local:ComboBoxItemString ValueString = "Song 1"/>
        <local:ComboBoxItemString ValueString = "Song 2"/>
        <local:ComboBoxItemString ValueString = "Song 3"/>
    </x:Array>
</Application.Resources>

这是班级:

namespace OCLMEditor
{
    /// This class provides us with an object to fill a ComboBox with
    /// that can be bound to string fields in the binding object.
    public class ComboBoxItemString
    {
        public string ValueString { get; set; }
    }
}

这是标记:

<ComboBox x:Name="comboSongOpen" ItemsSource="{StaticResource SongTitleString}" 
    DisplayMemberPath="ValueString" 
    SelectedValuePath="ValueString" 
    SelectedValue="{Binding SongTitle}">
    <ComboBox.MaxWidth>
        <Binding Path="ActualWidth" 
            ElementName="textWeeklyBibleReading"/>
    </ComboBox.MaxWidth>
</ComboBox>

一切都好。这个问题是,当歌曲标题显示在组合上时,我想在歌曲标题前加一个3位数字。例如:

001 - Song 1
002 - Song 2
003 - Song 3

最终,在应用程序的其他地方,我会想要使用组合框选择索引从资源中提取出正确的歌曲标题(没有前缀)。

这可能吗?

更新

如果我创建XML:

<?xml version="1.0" encoding="utf-8" ?>
<Settings>
  <SongTitles>
    <SongTitle Number="1" Title = "Jehovah's Attributes"/>
  </SongTitles>
</Settings>

并将其作为资源添加到WPF:

<Window.Resources>
    <XmlDataProvider x:Key="XmlData" Source="OCLM_Resources.xml" XPath="Settings/SongTitles" />
</Window.Resources>

然后使用:

<ComboBox x:Name="comboSongOpen"
           ItemsSource="{Binding Source={StaticResource XmlData}, XPath=./SongTitle}" DisplayMemberPath="@Title">
    <ComboBox.MaxWidth>
        <Binding Path="ActualWidth" 
            ElementName="textWeeklyBibleReading"/>
    </ComboBox.MaxWidth>
</ComboBox>

显示标题中的标题。但我不能完全理解使用ItemTemplate和/或stiching属性(格式化0.000)。

4 个答案:

答案 0 :(得分:3)

这是一个非常简单的纯xaml解决方案。你不需要改变你拥有的任何东西。

            //add this to your resource.  Obviously you should put this in code if you have lots of items
            <AlternationConverter x:Key="AlternateForegroundConverter">
                <s:Int16>1</s:Int16>
                <s:Int16>2</s:Int16>
                <s:Int16>3</s:Int16>
                <s:Int16>4</s:Int16>
                <s:Int16>5</s:Int16>
                //more if necessary
            </AlternationConverter>

        <ComboBox x:Name="comboSongOpen" ItemsSource="{StaticResource SongTitleString}" SelectedValuePath="ValueString" SelectedValue="{Binding SongTitle}" AlternationCount="99999" >
            <ComboBox.ItemTemplate>
                <DataTemplate DataType="local:ComboBoxItemString">
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="{Binding (ItemsControl.AlternationIndex), RelativeSource={RelativeSource AncestorType=ListBoxItem}, StringFormat='000 - ', Converter={StaticResource AlternateForegroundConverter}}" />
                        <TextBlock Text="{Binding ValueString}" />
                    </StackPanel>
                </DataTemplate>
            </ComboBox.ItemTemplate>
            <ComboBox.MaxWidth>
                <Binding Path="ActualWidth" ElementName="textWeeklyBibleReading"/>
            </ComboBox.MaxWidth>

编辑:需要此命名空间

xmlns:s="clr-namespace:System;assembly=mscorlib"

编辑:回复更新的问题

将DataTemplate更改为(在这种情况下,您不需要AlternationConverter)。

        <ComboBox.ItemTemplate>
            <DataTemplate DataType="local:ComboBoxItemString">
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding Number, StringFormat='000 - '}" />
                    <TextBlock Text="{Binding ValueString}" />
                </StackPanel>
            </DataTemplate>

//add Number property to you class
public class ComboBoxItemString
{
    public string ValueString { get; set; }
    public int Number { get; set; }
}

//add the array
<x:Array x:Key="SongTitleString" Type="local:ComboBoxItemString">
    <local:ComboBoxItemString ValueString = "Song 1" Number = "1" />
    <local:ComboBoxItemString ValueString = "Song 2" Number = "2" />
    <local:ComboBoxItemString ValueString = "Song 3" Number = "3" />
</x:Array>

总有一个很大的问题。你的名单是正确的。但是如果你选择一个项目,ComboBox将显示&#34; 001 - 耶和华的属性&#34;同样。要让它显示出耶和华的属性&#34;只是,您需要修改控件模板。

答案 1 :(得分:2)

正如EdPlunkett建议的那样,使用ComboBox的ItemTemplate参考以下示例。

<Window x:Class="ChkList_Learning.Window2"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:ChkList_Learning"
    mc:Ignorable="d"
    Title="Window2" Height="300" Width="300">
<Grid>
    <StackPanel>
        <ComboBox ItemsSource="{Binding SongList}" x:Name="songsCombo">
            <ComboBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="{Binding Title}"></TextBlock>
                        <TextBlock Text=" - "></TextBlock>
                        <TextBlock Text="{Binding SongName}"></TextBlock>
                    </StackPanel>
                </DataTemplate>
            </ComboBox.ItemTemplate>
        </ComboBox>
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="ID"></TextBlock>
            <TextBox Width="100" Text="{Binding ElementName=songsCombo,Path=SelectedItem.Title}"></TextBox>
        </StackPanel>
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="Song Name"></TextBlock>
            <TextBox Width="100"  Text="{Binding ElementName=songsCombo,Path=SelectedItem.SongName}"></TextBox>
        </StackPanel>
    </StackPanel>
</Grid>

    using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
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.Shapes;

namespace ChkList_Learning
{
    /// <summary>
    /// Interaction logic for Window2.xaml
    /// </summary>
    public partial class Window2 : Window
    {
        public Window2()
        {
            InitializeComponent();
            this.DataContext = new SongViewModel();
        }
    }

    class SongViewModel
    {
        public ObservableCollection<Song> SongList { get; set; }

        public SongViewModel()
        {
            SongList = new ObservableCollection<Song>();
            for (int i = 0; i < 10; i++)
            {
                Song song = new Song();
                song.Title = (i + 1).ToString();
                song.SongName = "Song Name" + (i + 1).ToString();
                song.AlbumName = "My Album";
                SongList.Add(song);
            }
        }
    }

    class Song
    {
        public string Title { get; set; }
        public string SongName { get; set; }

        public string AlbumName { get; set; }
    }
}

答案 2 :(得分:1)

我认为根据我对OP的评论,这更像是一个建议:

如果将歌曲列表卸载到文件中,则可以在初始化应用程序时读取文件以创建歌曲列表。文件的实际结构取决于您。通常使用CSV文件,因为这是一种分隔值(通过逗号)的简单方法,但您可以使用您喜欢的任何分隔符。

在这种情况下,考虑到一些简单的方法,你可以用C#读取文件,我甚至可以建议用新的行分隔你的歌曲名称。如果你这样做,编译你的歌曲列表就像这样简单:

string[] songList = System.IO.File.ReadAllLines(@"songlist.txt");
for (int i = 0; i < songList.Length; i++) {
     string newItem = ((i+1).ToString()) + " " + songList[i];
     combo1.Items.Add(newItem);
}

OR

List<string> songs = new List<string>();
for (int i = 0; i < songList.Length; i++) {
     songs.Add((i + 1).ToString() + " " + songList[i]);
}

combo1.ItemsSource = songs;

因此在这些例子中,组合框的内容将是

  

1首歌1

     

2 Song 2

编辑:根据帖子的最后部分

  

最终,在应用程序的其他地方,我会想要使用组合框选择索引从资源中提取出正确的歌曲标题(没有前缀)。

在您的示例中,格式为001 - Song 1

如果你只想要没有前缀的歌曲标题,selectedIndex,你有几个选择。

1)您可以在初始化应用程序时创建第二个列表,该列表不包含前缀。在编辑列表时,请创建第二个列表,然后添加不带前缀的歌曲名称。然后,您可以使用selectedIndex的{​​{1}}属性来引用此列表。

2)您可以使用ComboBox属性,然后使用一些字符串操作变体来提取歌曲名称。

selectedIndex

在此示例中,没有前缀的歌曲名称将位于string[] selectedSong = combo1.Items[0].ToString().Split('-'); 内。

答案 3 :(得分:0)

只需添加一个带有前置

的DisplayMemberPath
<Application.Resources>
    <x:Array x:Key="SongTitleString" Type="local:ComboBoxItemString">
        <local:ComboBoxItemString ValueString = "Song 1" ValueStringLong = "# 1 Song 1"/>
        <local:ComboBoxItemString ValueString = "Song 2" ValueStringLong = "# 2 Song 1"/>
        <local:ComboBoxItemString ValueString = "Song 3" ValueStringLong = "# 3 Song 1"/>
    </x:Array>
</Application.Resources>

DisplayMemberPath =“ValueStringLong”

相关问题