2

我想datacontext在单个Combobox. 我试过这样

this.courseList.DataContext = ldc.Courses.OrderBy(x => x.CourseID);
this.courseList.Items.Add("All");
this.courseList.Items.Add("Others");

但是,这InvalidOperationException was Unhandeled表明Items collection must be empty before using ItemsSource.

然后我就这样试了

this.courseList.Items.Add("All");       
foreach (var items in ldc.Courses.OrderBy(x => x.CourseID))
 {
   this.courseList.Items.Add(items);
 }
this.courseList.Items.Add("Others");       

它像这张图片一样工作 在此处输入图像描述 因为我在 XAML 设计中为此使用了 ItemTemplate,Combobox所以它并没有完全按照我的方式显示这两个值AllOthers.

这里是ItemTemplate

    <DataTemplate x:Key="CourseTemplate">
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="{Binding Path=CourseID}"/>
            <TextBlock Text=" : "/>
            <TextBlock Text="{Binding Path=CourseName}"/>
        </StackPanel>
    </DataTemplate>

...
 <ComboBox Name="courseList" VerticalAlignment="Top" SelectionChanged="courseList_SelectionChanged" IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding}" ItemTemplate="{StaticResource CourseTemplate}"/>

我希望它根据 DataTemplate 查看数据库条目和简单字符串,以及All分别Others如下图所示。 AllOthers在此处输入图像描述

有什么建议么。谢谢你。

4

3 回答 3

2

正如错误所说,您只能直接使用 ItemsSource 或 Items,而不是两者的混合。由于您本质上有两种不同类型的数据要以不同方式显示,您可以将它们全部添加到单个绑定集合中,然后让模板完成以不同方式呈现它们的工作。第 1 步是构建单个集合:

this.courseList.ItemsSource = new object[] { "All" }.Concat(ldc.Courses.OrderBy(x => x.CourseID)).Concat(new[] { "Others" });

您现在在集合中有 2 种类型的数据:字符串和您的对象,我假设它是 Course。字符串将根据需要显示,无需任何额外工作,但您只需将 DataTemplate 应用于 Course 对象。最简单的方法就是将您的 x:Key 替换为 DataType:

<DataTemplate DataType="{x:Type data:Course}">
    <StackPanel Orientation="Horizontal">
        <TextBlock Text="{Binding Path=CourseID}"/>
        <TextBlock Text=" : "/>
        <TextBlock Text="{Binding Path=CourseName}"/>
    </StackPanel>
</DataTemplate>

其中数据 xmlns 对应于 Course 对象的命名空间。

接下来只需从您的 ComboBox 中删除 ItemTemplate 属性,您应该会得到您要查找的内容。

如果您在同一范围内有其他地方也绑定了 Course 对象,但希望它们以不同方式显示,您可以将 DataType 模板的范围更本地化(即 Grid.Resources)或在 ComboBox 上使用 DataTemplateSelector。

于 2013-01-18T18:55:07.027 回答
1

由于ldc.Courses设置为DataContext, 并且您拥有ItemsSource="{Binding}"这意味着组合框直接绑定到您的集合。当您尝试像以前那样添加字符串时,这会产生一个问题,因为现在该集合既有字符串又有 Course 对象。

我认为这可能是最容易理解的解决方案。从您的第二种方法开始:

this.courseList.Items.Add("All");       
foreach (var items in ldc.Courses.OrderBy(x => x.CourseID))
 {
   this.courseList.Items.Add(items.CourseID.ToString() + " : " + items.CourseName);
 }
this.courseList.Items.Add("Others"); 

这将使您的组合框绑定到一个简单的字符串列表而不是对象,因此只要您在后台不需要其他信息,这将更容易消化,如果不尝试混合字符串和对象的其他答案之一进入同一个集合。这也意味着您不需要设置DataContextItemsSourceDataTemplate,因此请删除所有这些。

如果您想保留模板以添加更多控制,您可能需要再次查看其他一些答案。另一种选择是在您的课程对象上创建一个父类,该类也可以采用更一般的ALLOTHER案例,并在它们周围创建实际对象,这可能是最灵活的。这样您就不会以字符串和对象的集合结束,这将导致您在任何时候操作集合时都必须创建特殊的代码案例。

于 2013-01-18T18:48:42.657 回答
1

您可以通过结合使用 ItemTemplate 和转换器来解决此问题。

模板:

<ComboBox.ItemTemplate>
    <DataTemplate>
        <TextBlock Text="{Binding Converter={StaticResource ComboBoxItemConverter}}" /> 
    </DataTemplate>
</ComboBox.ItemTemplate>

转换器:

public class ComboBoxItemConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value is Courses)
        {
            var course = value as Courses;
            return course.CourseID + " : " + course.CourseName;
        }
        else
        {
            return value.ToString();
        }
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
于 2013-01-18T18:51:37.923 回答