Как я могу иметь элементы управления, связанные с изменением свойства, когда свойство изменяется данными, полученными по сети? - PullRequest
1 голос
/ 29 марта 2020

У меня есть класс пользователей с некоторыми свойствами, такими как имя, возраст, пол и сообщение, и поэтому у меня есть форма, в которой динамически создаются текстовые поля для каждого свойства каждого пользователя, и я привязываю каждое текстовое поле к соответствующим свойствам. .

Когда пользователи подключаются к моей программе и меняют свои свойства, текстовые поля не меняются.

Это мой класс пользователя:

using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace binding_network
{
    class user : INotifyPropertyChanged
    {
        private string _name;

        public string Name
        {
            get { return _name; }
            set
            {
                if (_name != value)
                {
                    _name = value;
                    NotifyPropertyChanged();
                }
            }
        }
        private int _age;

        public int Age
        {
            get { return _age; }
            set
            {
                if (_age != value)
                {
                    _age = value;
                    NotifyPropertyChanged();
                }
            }
        }
        private string _message;

        public string Message
        {
            get { return _message; }
            set
            {
                if (_message != value)
                {
                    _message = value;
                    NotifyPropertyChanged();
                }
            }
        }
        private string _gender;

        public string Gender
        {
            get { return _gender; }
            set
            {
                if (true)
                {
                    _gender = value;
                    NotifyPropertyChanged();
                }
            }
        }




        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

, и это код моей формы:

public partial class Form1 : Form
{
    private BindingSource userBindingSource = new BindingSource();
    BindingList<user> userList = new BindingList<user>();
    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        ///some code to create textboxes dynamically....

        txtName.DataBindings.Clear();
        txtName.DataBindings.Add("text", userBindingSource[userIndex], "name");
        txtAge.DataBindings.Clear();
        txtAge.DataBindings.Add("text", userBindingSource[userIndex], "age");
        txtGender.DataBindings.Clear();
        txtGender.DataBindings.Add("text", userBindingSource[userIndex], "gender");
        txtMessage.DataBindings.Clear();
        txtMessage.DataBindings.Add("text", userBindingSource[userIndex], "message");
    }
}

И этим способом я получаю данные по сети

private void GetMessage(object obj)
{
    user user1 = (user)obj;
    try
    {
        while (true)
        {
            byte[] buffer = new byte[1024];
            int rec = user1.SocketClient.Receive(buffer, 0, buffer.Length, 0);
            Array.Resize(ref buffer, rec);
            if (rec > 0)
            {
                user1.Name = BitConverter.ToString(buffer, 0);
                user1.Gender = BitConverter.ToString(buffer, 80);
                user1.Age = BitConverter.ToInt32(buffer, 96);
                user1.Message = BitConverter.ToString(buffer, 160);
            }
        }

    }
    catch (Exception ex)
    {

        MessageBox.Show(ex.ToString());
    }

}

Но после получения данных текстовые поля не обновляются sh

1 Ответ

0 голосов
/ 29 марта 2020

Кажется, что отсутствует много кода, но вот несколько вещей ...

userBindingSource не был подключен к userList.

Параметры привязки propertyName и dataMember имеют неверный корпус.

userIndex не определен.

Даже если бы это было так, привязка к userBindingSource[userIndex] не позволяет перемещаться по источнику (возможно, у вас все в порядке).

Так что давайте исправим это:

public partial class Form1 : Form
{
    private BindingSource userBindingSource = new BindingSource();
    BindingList<user> userList = new BindingList<user>();
    int userIndex = 0;

    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        userBindingSource.DataSource = userList;
        userIndex = userBindingSource.Position;

        ///some code to create textboxes dynamically....

        txtName.DataBindings.Clear();
        txtName.DataBindings.Add("Text", userBindingSource, "Name");
        txtAge.DataBindings.Clear();
        txtAge.DataBindings.Add("Text", userBindingSource, "Age");
        txtGender.DataBindings.Clear();
        txtGender.DataBindings.Add("Text", userBindingSource, "Gender");
        txtMessage.DataBindings.Clear();
        txtMessage.DataBindings.Add("Text", userBindingSource, "Message");
    }
}

Предполагая, что userList заполнено, вы можете теперь перемещаться по userBindingSource следующим образом:

// However you're tracking userIndex, or maybe...
// userIndex = userList.IndexOf(user1);
userBindingSource.Position = userIndex;

или любому из них:

userBindingSource.MoveFirst();
userBindingSource.MovePrevious();
userBindingSource.MoveNext();
userBindingSource.MoveLast();

И, наконец, удалите бесконечное число while (true) l oop в GetMessage.

На этом этапе, если ваши данные правильно получены и проанализированы, ваши TextBox элементы управления должны обновиться.

Edit ...

Итак, вы многопоточны, и это здорово.

Теперь мы должны убедиться, что все операции, которые приводят к изменению пользовательского интерфейса, выполнены правильный поток.

Позволяет сделать это (предполагая, что GetMessage определено внутри класса Form):

        if (rec > 0)
        {
            var name = BitConverter.ToString(buffer, 0);
            var gender = BitConverter.ToString(buffer, 80);
            var age = BitConverter.ToInt32(buffer, 96);
            var message = BitConverter.ToString(buffer, 160);

            this.Invoke(new Action(() =>
            {
                user1.Name = name;
                user1.Gender = gender;
                user1.Age = age;
                user1.Message = message;
            }));
        }

И это:

catch (Exception ex)
{
    this.Invoke(new Action(() => MessageBox.Show(ex.ToString())));
}

И Навигация по источнику привязки (если в другом потоке):

this.Invoke(new Action(() => userBindingSource.Position = userIndex));

Вы также можете использовать метод BeginInvoke.

...