-1

I have combobox inside a ItemsControl. How to bind the selected value of the combobox to the ItemsControl items with object not with int value. When i change the combobox everything is working well but after changing the PersonList with the new gender objects when the button clicked, combobox is not selected with the correct gender. I know when the new genders are added, binding is not working. But in my real situation the data are taken from database so the gender list is refreshed with the new one. How to create those kind of binding with object ?

Gender Class

    public class Gender : INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;
    
            private int id { get; set; }
            public int Id { get { return id; } set { id = value; OnPropertyChanged(nameof(Id)); } }
    
            private string name { get; set; }
            public string Name { get { return name; } set { name = value; OnPropertyChanged(nameof(Name)); } }
    
            protected virtual void OnPropertyChanged(string propertyName = null)
            {
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
            }
        }

Person Class

public class Person : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private string name { get; set; }
        public string Name { get { return name; } set { name = value; OnPropertyChanged(nameof(Name)); } }

        private string surname { get; set; }
        public string Surname { get { return surname; } set { surname = value; OnPropertyChanged(nameof(Surname)); } }

        private Gender personGender { get; set; }
        public Gender PersonGender { get { return personGender; } set { personGender = value; OnPropertyChanged(nameof(PersonGender)); } }

xml protected virtual void OnPropertyChanged(string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); }

Window xaml

    <Window x:Class="ComboText.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:ComboText"
            mc:Ignorable="d"
            Title="MainWindow" Height="450" Width="800">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="2*"/>
                <RowDefinition Height="1*"/>
            </Grid.RowDefinitions>
            <ItemsControl Grid.Row="0" x:Name="myGrid" ItemsSource="{Binding PersonList}" >
                <ItemsControl.ItemTemplate>
                    <DataTemplate >
                        <Grid Margin="10,10,0,0">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="1*"/>
                                <ColumnDefinition Width="1*"/>
                                <ColumnDefinition Width="1*"/>
                                <ColumnDefinition Width="1*"/>
                                <ColumnDefinition Width="2*"/>
                            </Grid.ColumnDefinitions>
                            <TextBlock Grid.Column="0" TextWrapping="WrapWithOverflow" Margin="20,0,20,0" Text="{Binding Name}" />
                            <TextBlock Grid.Column="1" TextWrapping="WrapWithOverflow" Margin="10,0,20,0" Text="{Binding Surname}" />
                            <TextBlock Grid.Column="3" TextWrapping="WrapWithOverflow" Margin="10,0,20,0" Text="{Binding PersonGender.Id}" />
                            <ComboBox  Grid.Column="4" x:Name="tagComboBox" MinWidth="100" Margin="10,0,20,0"  SelectedValue="{Binding PersonGender, Mode=TwoWay}"  ItemsSource="{Binding GenderList, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}" DisplayMemberPath="Name"></ComboBox>
                        </Grid>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
            <Button Grid.Row="1" Click="Button_Click">CLICK</Button>
        </Grid>
    </Window>

Window code behind

 public partial class MainWindow : Window, INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public ObservableCollection<Person> personList { get; set; }
        public ObservableCollection<Person> PersonList { get { return personList; } set { personList = value; OnPropertyChanged(nameof(PersonList)); } }

        public ObservableCollection<Gender> genderList { get; set; }
        public ObservableCollection<Gender> GenderList { get { return genderList; } set { genderList = value; OnPropertyChanged(nameof(GenderList)); } }

        //Gender male, female, none;

        public MainWindow()
        {
            InitializeComponent();
            DataContext = this;

            PersonList = new ObservableCollection<Person>();
            GenderList = new ObservableCollection<Gender>();

            Person sahin = new Person { Name = "Sahin", Surname = "Atam" };
            Person seda = new Person { Name = "Seda", Surname = "Atam" };
            Person umran = new Person { Name = "Ümran", Surname = "Atam" };

            personList.Add(sahin);
            personList.Add(seda);
            personList.Add(umran);


            Gender male = new Gender { Id=1, Name = "Male" };
            Gender female = new Gender { Id=2, Name = "Female" };
            Gender none = new Gender {Id=3, Name = "None" };

            GenderList.Add(male);
            GenderList.Add(female);
            GenderList.Add(none);
        }

        //When propert changes, notify
        protected virtual void OnPropertyChanged(string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
          Gender genderMale = new Gender {Id=1, Name = "Male" };
          Gender genderFemale = new Gender {Id=2, Name = "Female" };

           Person ali = new Person { Name = "Ali", Surname = "Atam" ,PersonGender=genderMale};
           Person muk= new Person { Name = "Mukaddes", Surname = "Atam" , PersonGender= genderFemale };

            PersonList.Clear();
            PersonList.Add(ali);
            PersonList.Add(muk);

        }
    }
EldHasp
  • 6,079
  • 2
  • 9
  • 24
nihasmata
  • 652
  • 1
  • 8
  • 28
  • 1
    You must ensure that the Gender object returned from `Person.PersonGender` is equal to the value in the `GenderList`. If you can't rely on using the same instance, you would have to override the `Gender.Equals` method by implementing the `IEquatable` interface. This way you can define equality based on the values instead of instance equality. – BionicCode Sep 12 '22 at 14:52

1 Answers1

0

Pick the existing Gender objects from the GenderList instead of creating new ones that are not included in the list of selectable genders:

private void Button_Click(object sender, RoutedEventArgs e)
{
    Gender genderMale = GenderList.FirstOrDefault(x => x.Id == 1);
    Gender genderFemale = GenderList.FirstOrDefault(x => x.Id == 2);

    Person ali = new Person { Name = "Ali", Surname = "Atam", PersonGender = genderMale };
    Person muk = new Person { Name = "Mukaddes", Surname = "Atam", PersonGender = genderFemale };

    PersonList.Clear();
    PersonList.Add(ali);
    PersonList.Add(muk);
}
mm8
  • 163,881
  • 10
  • 57
  • 88