stackovrflo
stackovrflo

Reputation: 93

Combobox Empty Item

I am trying to bind a combobox with an empty item. For this I am using the CompositeCollection as I have read in many of the questions.

This is working currently. However using a composite collection messes up the grouping that I had. Either I get the blank in the combobox or I get the grouping. I want both be available.

Here is the sample code that I have been playing with:

Xaml

<Window.Resources>
    <local:CourseConverter x:Key="CourseConverter" />
    <DataTemplate DataType="{x:Type local:Course}">
        <TextBlock Text="{Binding Path=CourseName}" />
    </DataTemplate>
    <CollectionViewSource x:Key="CoursesCVS" Source="{Binding Courses}">
        <CollectionViewSource.GroupDescriptions>
            <PropertyGroupDescription PropertyName="Major" />
        </CollectionViewSource.GroupDescriptions>
    </CollectionViewSource>
</Window.Resources>
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="0.2*"/>
        <RowDefinition Height="Auto "/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <TextBlock Text="Select Course" Grid.Row="1" Margin="15,5,0,5" Width="200" />
    <ComboBox Grid.Row="2" Width="200" Margin="15,5,0,5"
              ItemsSource="{Binding Source={StaticResource CoursesCVS}}"
              SelectedItem="{Binding SelectedCourse, Converter={StaticResource CourseConverter}}">
        <ComboBox.GroupStyle>
            <GroupStyle>
                <GroupStyle.HeaderTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Name}"/>
                    </DataTemplate>
                </GroupStyle.HeaderTemplate>
            </GroupStyle>
        </ComboBox.GroupStyle>
        <!--<ComboBox.ItemsSource>
            <CompositeCollection>
                <ComboBoxItem Content="" />
                <CollectionContainer Collection="{Binding Source={StaticResource CoursesCVS}}" />
            </CompositeCollection>
        </ComboBox.ItemsSource>-->
    </ComboBox>
    <TextBlock Text="{Binding SelectedCourse.CourseName}" Grid.Row="3" Margin="15,5,0,5" Width="200" />
</Grid>

viewmodel and supporting classes:

public class Course
{
    public int CourseID { get; set; }
    public string CourseName { get; set; }
    public string Major { get; set; }
}

public class MainWindowViewModel : INotifyPropertyChanged
{
    public MainWindowViewModel() 
    {
        _courses = new List<Course>();
        _courses.Add(new Course { CourseID = 1, CourseName = "Math 107", Major = "Math" });
        _courses.Add(new Course { CourseID = 1, CourseName = "Biology 110", Major = "Biology" });
        _courses.Add(new Course { CourseID = 1, CourseName = "Chemistry 123", Major = "Chemistry" });
        _courses.Add(new Course { CourseID = 1, CourseName = "Spanish 112", Major = "Biology" });
        _courses.Add(new Course { CourseID = 1, CourseName = "Molecular 114", Major = "Biology" });
    }

    private List<Course> _courses;

    public List<Course> Courses
    {
        get { return _courses; }
        set { _courses = value; OnPropertyChanged(); }
    }

    private Course _selectedCourse;

    public Course SelectedCourse
    {
        get { return _selectedCourse; }
        set { _selectedCourse = value; OnPropertyChanged(); }
    }


    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged([CallerMemberName]string propertyName = "")
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

}

public class CourseConverter : IValueConverter
{

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return value;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value is Course)
            return value;
        else
            return null;
    }
}

Is there something that I am missing to make it work with and without grouping. For removing grouping, I remove inline ItemSource declaration and use the commented code. This shows the blank.

Upvotes: 0

Views: 418

Answers (1)

Sheridan
Sheridan

Reputation: 69959

In WPF, we work with data items, not UI elements. We declare DataTemplates to define what our data items should look like in any UI container. Using this method, we let the Framework take care of displaying the UI and we concentrate on the data. So, to display an empty UI element in WPF, you just have to add an empty data item into your collection and let the DataTemplate do its work:

_courses.Add(new Course());

This would be rendered simply as an empty item as it has no data to be displayed in any data bound controls. So try declaring a DataTemplate in the ComboBox.ItemTemplate property, or even just setting the DisplayMemberPath to the relevant Course property if you only want to display one value.

Upvotes: 1

Related Questions