Presentation of a WPF Master Part with List and Combobox with Binding

I have been searching for the answer to my question for several days, but cannot find a solution.

The problem is that combobox updates the Test object in the User class with the previously selected users.

i.e. you select user2 and user2 has test2, then select user5, which has test5. Now, if you select user2 again, it will show that it has test5.

Here is the code. I have two classes, Users and Tests. And two ObservableCollections for each of them. Here's how I set them up:

public class User
{
    public string Name { get; set; }
    public int test { get; set; }
    public test userTest { get; set; }
}

public class test
{
    public int ID { get; set; }
    public String Name { get; set; }
}

public class ListOfTests:ObservableCollection<test>
{
    public ListOfTests()
    {
        for (int i = 0; i < 4; i++)
        {
            test newTest = new test();
            newTest.ID = i;
            newTest.Name = "Test " + i;
            Add(newTest);
        }
    }
}

public class ListOfUsers: ObservableCollection<User>
{
    public ListOfUsers()
    {
        ListOfTests testlist = new ListOfTests();
        for (int i = 0; i < 10; i++)
        {
            User newUser = new User();
            newUser.Name = "User " + i;
            newUser.ID = i;
            newUser.userTest = testlist[i];
            Add(newUser);
        }
    }
}

And XAML:

<Window x:Class="ComboboxTest.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ComboboxTest"
Title="Window1" Height="300" Width="300">
<StackPanel x:Name="SP1">
    <StackPanel.Resources>
        <local:ListOfTests x:Key="ListOfTests" />
    </StackPanel.Resources>
    <ListBox ItemsSource="{Binding}" DisplayMemberPath="Name" IsSynchronizedWithCurrentItem="True"/>
    <TextBox Text="{Binding Path=Name}" Foreground="Black"  />
    <TextBox Text="{Binding Path=userTest}" />  
    <ComboBox SelectedItem="{Binding Path=userTest}" 
              SelectedValue="{Binding Path=userTest.ID}"
              ItemsSource="{Binding Source={StaticResource ListOfTests}}" 
              DisplayMemberPath="Name" 
              SelectedValuePath="ID"

              Foreground="Black" />
</StackPanel>

Now, if I changed the binding on SelectedItem to "{Binding Path = userTest, Mode = OneWay}", then it works, but I cannot change it manually.

... .Net 4.0 (VS2010), ...

- ?

+3
2

, , WPF , . , INotifyPropertyChanged . , User :

public class User : INotifyPropertyChanged
{
    private string name = string.Empty;
    public string Name
    {
        get { return this.name; }
        set
        {
            this.name = value;
            this.OnPropertyChanged("Name");
        }
    }

    private int test = 0;
    public int Test
    {
        get { return this.test; }
        set
        {
            this.test = value;
            this.OnPropertyChanged("Test");
        }
    }

    private test userTest = null;
    public test UserTest
    {
        get { return this.userTest; }
        set
        {
            this.userTest = value;
            this.OnPropertyChanged("UserTest");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string propName)
    {
        PropertyChangedEventHandler eh = this.PropertyChangd;
        if(null != eh)
        {
            eh(this, new PropertyChangedEventArgs(propName));
        }
    }
}

, , test.

WPF PropertyChanged . , ComboBox 2.

: , , . , , (, DataContext Window), :

ViewModel, DataContext Window. :

class ViewModel : INotifyPropertyChanged
{
    public ViewModel()
    {
        for(int i = 0; i < 4; i++)
        {
            this.tests.Add(new Test()
            {
                ID = i,
                Name = "Test " + i.ToString(),
            });
        }

        for(int i = 0; i < 4; i++)
        {
            this.users.Add(new User()
            {
                Name = "User " + i.ToString(),
                ID = i,
                UserTest = this.tests[i],
            });
        }
    }

    private ObservableCollection<User> users = new ObservableCollection<User>();
    public IEnumerable<User> Users
    {
        get { return this.users; }
    }

    private ObservableCollection<Test> tests = new ObservableCollection<Test>();
    public IEnumerable<Test> Tests
    {
        get { return this.tests; }
    }

    private User currentUser = null;
    public User CurrentUser
    {
        get { return this.currentUser; }
        set
        {
            this.currentUser = value;
            this.OnPropertyChanged("CurrentUser");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string propName)
    {
        var eh = this.PropertyChanged;
        if(null != eh)
        {
            eh(this, new PropertyChangedEventArgs(propName));
        }
    }
}

. , , , ListOfTests ItemsSource ComboBox, ListOfUsers. , , .

XAML Window :

<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfApplication1"
    Title="Window1" Height="300" Width="300">
    <StackPanel>
        <ListBox ItemsSource="{Binding Path=Users}"
                 SelectedItem="{Binding Path=CurrentUser}"
                 DisplayMemberPath="Name"
                 IsSynchronizedWithCurrentItem="True">
        </ListBox>
        <TextBox Text="{Binding Path=CurrentUser.Name}" />
        <TextBox Text="{Binding Path=CurrentUser.UserTest.Name}" />
        <ComboBox ItemsSource="{Binding Path=Tests}"
                  SelectedItem="{Binding Path=CurrentUser.UserTest}"
                  DisplayMemberPath="Name" />
    </StackPanel>
</Window>

CurrentUser. ListBox.SelectedItem, ComboBox.SelectedItem CurrentUser.UserTest. ComboBox, , ListBox.

Visual Studio 2008 SP1, , , . , , , .

+5

,

, .

public class User : INotifyPropertyChanged
{
    private string name;
    public string Name 
    {
        get
        {
            return name;
        }
        set
        {
            name = value;
            OnPropertyChanged("Name");
        }
    }

    private int iD;
    public int ID 
    {
        get
        {
            return iD;
        }
        set
        {
            iD = value;
            OnPropertyChanged("ID");
        }
    }

    private test userTest;
    public test UserTest 
    {
        get
        {
            return userTest;
        }
        set
        {
            userTest = value;
            OnPropertyChanged("UserTest");
        }
    }


    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string propName)
    {
        PropertyChangedEventHandler eh = this.PropertyChanged;
        if (null != eh)
        {
            eh(this, new PropertyChangedEventArgs(propName));
        }
    }
}

, .

0

Source: https://habr.com/ru/post/1714096/


All Articles