2

datacontext静的な値を1つに割り当てたいと思います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を使用したため、この2つの値と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}"/>

Allデータベースエントリと単純な文字列、およびそれぞれ下の画像のように、 DataTemplateに従って表示する必要がOthersあります。AllOthersここに画像の説明を入力してください

助言がありますか。ありがとうございました。

4

3 に答える 3

2

エラーが示すように、ItemsSourceまたはItemsを直接使用することはでき、2つを組み合わせて使用​​することはできません。基本的に、異なる方法で表示したい2つの異なるタイプのデータがあるため、それらすべてを1つのバインドされたコレクションに追加してから、テンプレートに異なる方法でレンダリングする作業を任せることができます。ステップ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はとして設定されているのでDataContextItemsSource="{Binding}"これはコンボボックスがコレクションに直接バインドされていることを意味します。これにより、コレクションに文字列とコースオブジェクトの両方が含まれるようになったため、文字列を追加しようとすると問題が発生します。

これがおそらく最も理解しやすい解決策になると思います。2番目のアプローチから始めます。

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"); 

これにより、コンボボックスがオブジェクトではなく文字列の単純なリストにバインドされたままになります。バックグラウンドで他の情報が必要ない限り、文字列とオブジェクトを組み合わせた他の回答の1つを試さない場合でも、これは簡単に消化できます。同じコレクションに。DataContextこれは、、、、ItemsSourceまたはを設定する必要がないことも意味するDataTemplateので、それらをすべて消去します。

テンプレートを保持してもう少し制御を追加したい場合は、他のいくつかの回答を確認することをお勧めします。もう1つの方法は、コースオブジェクトの上に親クラスを作成することです。これにより、より一般的なケースALLとケースを取得し、OTHERそれらの周りに実際のオブジェクトを作成することができます。おそらく最も柔軟性があります。この方法では、文字列とオブジェクトの両方のコレクションで終了することはありません。そのため、コレクションを操作するたびに特別なコードケースを作成する必要があります。

于 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 に答える