C# 在组合框中将前缀添加到ItemSource值

C# 在组合框中将前缀添加到ItemSource值,c#,wpf,combobox,itemsource,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"

这是我的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>
这是标记:

<ComboBox x:Name="comboSongOpen" ItemsSource="{StaticResource SongTitleString}" 
    DisplayMemberPath="ValueString" 
    SelectedValuePath="ValueString" 
    SelectedValue="{Binding SongTitle}">
    <ComboBox.MaxWidth>
        <Binding Path="ActualWidth" 
            ElementName="textWeeklyBibleReading"/>
    </ComboBox.MaxWidth>
</ComboBox>
最后,在应用程序的其他地方,我希望使用组合框selected index从参考资料中提取没有前缀的正确歌曲标题

这可能吗

更新:

如果创建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和/或将0.000的格式粘贴到属性上。

根据我在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);
}

在本例中,不带前缀的歌曲名称将位于selectedSong[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);
}

在此示例中,不带前缀的歌曲名称将位于selectedSong[1]内。

根据EdPlunkett的建议,请使用组合框的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>

正如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>

这是一个非常简单的纯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>
编辑:回应更新的问题

将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>

然而,有一个很大的问题。你的清单是正确的。但是如果您选择一个项目,组合框也会显示001-耶和华属性。要使其仅显示耶和华属性,您需要修改控件模板。

这里有一个非常简单的纯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>
编辑:回应更新的问题

将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>

然而,有一个很大的问题。你的清单是正确的。但是如果您选择一个项目,组合框也会显示001-耶和华属性。要使其仅显示耶和华的属性,您需要修改控件模板。

只需添加一个带有前缀的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

只需添加一个带有前缀的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

您真的是在硬编码ComboBox条目,还是通过ComboBox.Items.Add或数据源插入它们?目前,154个标题的大列表作为一个资源存在于app.xml文件中。最终我需要支持本地化。我没有使用Add函数调用。根据我的问题,我正在使用ItemSource。我可以建议将歌曲列表放入一个文件中,并在应用程序初始化时读取该文件,然后通过Items.add添加它们吗。这是一个非常简单的条目编号/索引解决方案。最好的选择是项目模板。您需要向项添加索引属性。在应用程序的其他地方使用combobox选择的索引不是一个好主意。只需将ComboBox.SelectedItem绑定到viewmodel中适当类型的属性即可。事实上,ComboBoxItemString是一个有趣的名称,用于表示歌曲的类。从概念上讲,在WPF中考虑这一点的方式是,您有一个歌曲对象列表。写一个代表歌曲的类,给它适当的属性:标题,艺术家,发行年份,等等。在项目模板中适当地显示属性。您真的对ComboBox条目进行了硬编码,还是通过ComboBox.Items.Add或数据源插入了这些条目?目前,包含154个标题的大列表作为资源存在于app.xml文件中。最终我需要支持本地化。我没有使用Add函数调用。根据我的问题,我正在使用ItemSource。我可以建议将歌曲列表放入一个文件中,并在应用程序初始化时读取该文件,然后通过Items.add添加它们吗。这是一个非常简单的条目编号/索引解决方案。最好的选择是项目模板。您需要向项添加索引属性。使用组合

从应用程序的其他地方选择索引框不是一个好主意。只需将ComboBox.SelectedItem绑定到viewmodel中适当类型的属性即可。事实上,ComboBoxItemString是一个有趣的名称,用于表示歌曲的类。从概念上讲,在WPF中考虑这一点的方式是,您有一个歌曲对象列表。编写一个表示歌曲的类,为其提供适当的属性:标题、艺术家、发行年份等。在项目模板中适当显示属性。谢谢。我想使用一个XML文件,其中包含歌曲标题和歌曲编号作为属性。。我只是希望,如果数据被转换成另一种格式,比如每个项目有2个属性的XML,我们仍然可以进行绑定。我明天会看看你写的东西。另一件事是,由于本地化的原因,文件需要放在资源中。是的,还有其他方法来存储一些项目列表,这主要取决于您。但是,如果您确实使用某种存储方法而不是硬编码,则将项目放入组合框的方法通常类似于此方法。这也会使组合框变为文本1歌曲1、2歌曲2等。我已根据您的操作的底部更新了答案拆分字符串是可怕的,完全没有必要。您将索引与ItemTemplateThank放在一起。我想使用一个XML文件,其中包含歌曲标题和歌曲编号作为属性。。我只是希望,如果数据被转换成另一种格式,比如每个项目有2个属性的XML,我们仍然可以进行绑定。我明天会看看你写的东西。另一件事是,由于本地化的原因,文件需要放在资源中。是的,还有其他方法来存储一些项目列表,这主要取决于您。但是,如果您确实使用某种存储方法而不是硬编码,则将项目放入组合框的方法通常类似于此方法。这也会使组合框变为文本1歌曲1、2歌曲2等。我已根据您的操作的底部更新了答案拆分字符串是可怕的,完全没有必要。您将索引与ItemTemplate放在一起谢谢。我明天再看这个。看看能否从XML文件资源中填充歌曲列表。谢谢。我明天再看这个。看看能否从XML文件资源中填充歌曲列表。谢谢。我更新的问题在xml中有两个属性。我们能利用它吗?你看,我有154个头衔。因此,如果我们可以结合格式化我的xml中的项目。我们是赢家。可行?是的,但你确定要使用第二个属性吗?这里的想法是你根本不需要手动设置数字。如果你把第100首歌移到第一首呢?您必须修复100首歌曲的编号。顺序不会改变。它们代表书中的歌曲。所以它是固定的。我更喜欢管理一组数据。如果可能的话,请。像最初那样管理app.xaml中的数据有什么问题?我看不到任何情况下,您最终会管理多个数据集。@AndrewTruckle我认为将其保存在app.config中是最好的。这意味着没有要包含的外部文件。您可以在不重新编译的情况下更改歌曲。您也可以轻松地进行本地化。根据你现在的问题,你根本不需要索引。我们可以将ComboBoxItemString类对象返回到combobox的SelectedItem。谢谢。我更新的问题在xml中有两个属性。我们能利用它吗?你看,我有154个头衔。因此,如果我们可以结合格式化我的xml中的项目。我们是赢家。可行?是的,但你确定要使用第二个属性吗?这里的想法是你根本不需要手动设置数字。如果你把第100首歌移到第一首呢?您必须修复100首歌曲的编号。顺序不会改变。它们代表书中的歌曲。所以它是固定的。我更喜欢管理一组数据。如果可能的话,请。像最初那样管理app.xaml中的数据有什么问题?我看不到任何情况下,您最终会管理多个数据集。@AndrewTruckle我认为将其保存在app.config中是最好的。这意味着没有要包含的外部文件。您可以在不重新编译的情况下更改歌曲。您也可以轻松地进行本地化。根据你现在的问题,你根本不需要索引。我们可以将ComboBoxItemString类对象返回到combobox的SelectedItem。
<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>