0

My problem is EMPTY Combobox list. I've walked through a lot of web site (during 3 days), but couldn't figure out it.
I've written a program that show a List of Students, clicking I can change properties them. So, I can change succsefuly all properties except Faculty (ComboBox).
Click to see View my programm
I used MVVM....
I have Class Student (Model). Here, General is enum StudentFaculty....

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _15._01._2018.Model
{
    public enum StudentFaculty { Programmer, SysAdministration, Designer};
    class Student : INotifyPropertyChanged
    {
        private string _name;
        private string _lastname;
        private StudentFaculty _faculty;
        private double _averageMark;

        public string Name
        {
            get { return _name; }
            set
            {
                if(_name == value) return;
                _name = value;
                OnPropertyChanged("Name");
            }
        }
        public string Lastname
        {
            get { return _lastname; }
            set
            {
                if (_lastname == value) return;
                _lastname = value;
                OnPropertyChanged("Lastname");
            }
        }
        public StudentFaculty Faculty
        {
            get { return _faculty; }
            set
            {
                if (_faculty == value) return;
                _faculty = value;
                OnPropertyChanged("Faculty");
            }
        }
        public double AverageMark
        {
            get { return _averageMark; }
            set
            {
                if (_averageMark == value) return;
                _averageMark = value;
                OnPropertyChanged("AverageMark");
            }
        }
        public Student() { }
        public Student(string name, string lastname, StudentFaculty faculty, double averageMark)
        {
            Name = name;
            Lastname = lastname;
            Faculty = faculty;
            AverageMark = averageMark;
        }
        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged(string property)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(property));
        }
    }
}

Class ApplicationViewModel. Here, I make List (Faculties) from enum in Constructor, also SelectedFaculty...

using _15._01._2018.Model;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _15._01._2018.ViewModel
{
    class ApplicationViewModel : INotifyPropertyChanged
    {
        private Student _selectedStudent;
        private string _selectedFaculty;
        public ObservableCollection<Student> Students { get; set; }
        public List<string> Faculties { get; set; }
        public Student SelectedStudent
        {
            get { return _selectedStudent; }
            set
            {
                if (_selectedStudent == value) return;
                _selectedStudent = value;
                OnChangedProperty("SelectedStudent");
            }
        }
        public string SelectedFaculty
        {
            get { return _selectedFaculty; }
            set
            {
                if (_selectedFaculty == value) return;
                _selectedFaculty = value;
                OnChangedProperty("SelectedFaculty");
            }
        }
        public ApplicationViewModel()
        {
            Students = new ObservableCollection<Student>
            {
                new Student("Vova", "Zyabkin", StudentFaculty.Programmer, 9.4),
                new Student("Vadym", "Lazariev", StudentFaculty.Programmer, 9),
                new Student("SvEta", "Belyaeva", StudentFaculty.Designer, 9.8),
                new Student("Vova", "Skachkov", StudentFaculty.SysAdministration, 8.7)
            };
            Faculties = new List<string>(Enum.GetNames(typeof(StudentFaculty)));
        }
        public event PropertyChangedEventHandler PropertyChanged;
        public void OnChangedProperty(string property)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(property));
        }
    }
} 

XAML

<Window x:Class="_15._01._2018.MainWindow"
        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:_15._01._2018"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <Style TargetType="TextBlock">
            <Setter Property="FontSize" Value="14" />
        </Style>
        <Style TargetType="TextBox">
            <Setter Property="FontSize" Value="14" />
        </Style>
    </Window.Resources>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <ListBox ItemsSource="{Binding Students}" SelectedItem="{Binding SelectedStudent}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Vertical">
                        <TextBlock Text="{Binding Path=Name}"></TextBlock>
                        <TextBlock Text="{Binding Path=Lastname}"></TextBlock>
                        <!--<TextBlock Text="{Binding Path=Faculty}"></TextBlock>-->
                        <TextBlock Text="{Binding Path=AverageMark}"></TextBlock>
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
        <Grid Grid.Column="1">
            <StackPanel DataContext="{Binding SelectedStudent}">
                <TextBlock Text="D A T A"></TextBlock>
                <TextBlock Text="Name:"></TextBlock>
                <TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}"></TextBox>
                <TextBlock Text="Lastname:"></TextBlock>
                <TextBox Text="{Binding Lastname, UpdateSourceTrigger=PropertyChanged}"></TextBox>
                <TextBlock Text="Faculty:"></TextBlock>
                <ComboBox ItemsSource="{Binding Faculties}" SelectedItem="{Binding SelectedFaculty}">

                </ComboBox>
                <TextBlock Text="Average Mark:"></TextBlock>
                <TextBox Text="{Binding AverageMark, UpdateSourceTrigger=PropertyChanged}"></TextBox>
            </StackPanel>
        </Grid>
    </Grid>
</Window>

I have idea to create a Class with String property Faculty, but it's like with ListBox and Student.

1
  • You could try to use the original enum (StudentFaculty) instead of a string. Or alternatively create a complex type for Faculty with a string property called Name, and make the Faculties property as a list of that instead of a string list - and add the DisplayMemberPath="Name" attribute in your xaml to your combobox. Commented Jan 17, 2018 at 19:35

1 Answer 1

1

To start off with, the DataContext for your ComboBox is set to the SelectedStudent, not the ApplicationViewModel (see the parent StackPanel). Second, you have the Faculties property returning a list of String, but the Student class has a property of StudentFaculty (binding for SelectedValue won't work).

Try the following:

Models/ViewModels:

class ApplicationViewModel : INotifyPropertyChanged
{
    private Student _selectedStudent;
    private StudentFaculty _selectedFaculty;
    public ObservableCollection<Student> Students { get; set; }
    public ObservableCollection<StudentFaculty> Faculties { get; set; }
    public Student SelectedStudent
    {
        get => _selectedStudent;
        set
        {
            if (_selectedStudent == value) return;
            _selectedStudent = value;
            OnChangedProperty("SelectedStudent");
        }
    }
    public StudentFaculty SelectedFaculty
    {
        get => _selectedFaculty;
        set
        {
            if (_selectedFaculty == value) return;
            _selectedFaculty = value;
            OnChangedProperty("SelectedFaculty");
        }
    }
    public ApplicationViewModel()
    {
        Students = new ObservableCollection<Student>
        {
            new Student("Vova", "Zyabkin", StudentFaculty.Programmer, 9.4),
            new Student("Vadym", "Lazariev", StudentFaculty.Programmer, 9),
            new Student("SvEta", "Belyaeva", StudentFaculty.Designer, 9.8),
            new Student("Vova", "Skachkov", StudentFaculty.SysAdministration, 8.7)
        };
        Faculties = new ObservableCollection<StudentFaculty>(Enum.GetValues(typeof(StudentFaculty)).OfType<StudentFaculty>());
    }
    public event PropertyChangedEventHandler PropertyChanged;

    public void OnChangedProperty(string property) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
}

public enum StudentFaculty { Programmer, SysAdministration, Designer };
class Student : INotifyPropertyChanged
{
    private string _name;
    private string _lastname;
    private StudentFaculty _faculty;
    private double _averageMark;

    public string Name
    {
        get => _name;
        set
        {
            if (_name == value) return;
            _name = value;
            OnPropertyChanged("Name");
        }
    }
    public string Lastname
    {
        get => _lastname;
        set
        {
            if (_lastname == value) return;
            _lastname = value;
            OnPropertyChanged("Lastname");
        }
    }
    public StudentFaculty Faculty
    {
        get => _faculty;
        set
        {
            if (_faculty == value) return;
            _faculty = value;
            OnPropertyChanged("Faculty");
        }
    }
    public double AverageMark
    {
        get => _averageMark;
        set
        {
            if (_averageMark == value) return;
            _averageMark = value;
            OnPropertyChanged("AverageMark");
        }
    }
    public Student() { }
    public Student(string name, string lastname, StudentFaculty faculty, double averageMark)
    {
        Name = name;
        Lastname = lastname;
        Faculty = faculty;
        AverageMark = averageMark;
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged(string property) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
}

XAML:

<Window x:Class="WpfApp4.MainWindow"
    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:converters="clr-namespace:WpfApp4.Views.Converters"
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
    xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
    xmlns:viewModels="clr-namespace:WpfApp4.ViewModels"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
    <viewModels:ApplicationViewModel />
</Window.DataContext>
<Window.Resources>
    <Style TargetType="TextBlock">
        <Setter Property="FontSize" Value="14" />
    </Style>
    <Style TargetType="TextBox">
        <Setter Property="FontSize" Value="14" />
    </Style>
    <CollectionViewSource x:Key="Faculties" Source="{Binding Faculties}"></CollectionViewSource>
</Window.Resources>
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition></ColumnDefinition>
        <ColumnDefinition></ColumnDefinition>
    </Grid.ColumnDefinitions>
    <ListBox ItemsSource="{Binding Students}" SelectedItem="{Binding SelectedStudent}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Vertical">
                    <TextBlock Text="{Binding Path=Name}"></TextBlock>
                    <TextBlock Text="{Binding Path=Lastname}"></TextBlock>
                    <!--<TextBlock Text="{Binding Path=Faculty}"></TextBlock>-->
                    <TextBlock Text="{Binding Path=AverageMark}"></TextBlock>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
    <Grid Grid.Column="1">
        <StackPanel DataContext="{Binding SelectedStudent}">
            <TextBlock Text="D A T A"></TextBlock>
            <TextBlock Text="Name:"></TextBlock>
            <TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}"></TextBox>
            <TextBlock Text="Lastname:"></TextBlock>
            <TextBox Text="{Binding Lastname, UpdateSourceTrigger=PropertyChanged}"></TextBox>
            <TextBlock Text="Faculty:"></TextBlock>
            <ComboBox ItemsSource="{Binding Source={StaticResource Faculties}}" SelectedValue="{Binding Faculty, Mode=TwoWay}">

            </ComboBox>
            <TextBlock Text="Average Mark:"></TextBlock>
            <TextBox Text="{Binding AverageMark, UpdateSourceTrigger=PropertyChanged}"></TextBox>
        </StackPanel>
    </Grid>
</Grid>

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.