Двусторонняя привязка в WPF — когда объект кеша находится внутри другого связанного объекта.C#

Место общения программистов C#
Ответить
Anonymous
 Двусторонняя привязка в WPF — когда объект кеша находится внутри другого связанного объекта.

Сообщение Anonymous »

Я не могу заставить двустороннюю привязку в WPF работать должным образом.
Я получил класс UserCache, имеющий свойство Current. Объект этого класса помещается в класс фасада ConnectedUserCache, который также имеет свойство Current.
MainWindow.xaml

Код: Выделить всё

[...]



[...]










Vorname:

Nachname:

Telefon:


[...]

MainWindow.xaml.cs

Код: Выделить всё

   public partial class MainWindow : Window
{
private ConnectedUserCache _cache = new ConnectedUserCache();

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

// Otherwise DataGrid would not be filled at the beginning
_cache.RefreshAsync();
ReloadDataGrid(_cache);
}

private void ReloadDataGrid(ConnectedUserCache? cache)
{
UserDataGrid.ItemsSource = null;
UserDataGrid.ItemsSource = cache.UsersShown;
}

private void Button_SeachUserInCache_Click(object sender, RoutedEventArgs e)
{
var cache = DataContext as ConnectedUserCache;
if (cache == null) return;

cache.SearchCurrentUser();

// Reload datasource of datagrid
UserDataGrid.ItemsSource = null;
UserDataGrid.ItemsSource = cache.UsersShown;
}
[...]

ConnectedUserCache.cs

Код: Выделить всё

using System.Collections.ObjectModel;
using System.ComponentModel;
using UserWpfClient.Http;
using UserWpfClient.LocalData;

namespace UserWpfClient
{
internal class ConnectedUserCache : INotifyPropertyChanged
{
private UserCache _userCache = new UserCache();
private HttpUserClient _userClient = new HttpUserClient();

public ConnectedUserCache() {}
protected virtual void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
[...]

public event PropertyChangedEventHandler? PropertyChanged;

public UserModelView Current
{
get { return _userCache.Current; }
set
{
_userCache.Current = value;
OnPropertyChanged(nameof(Current));
}
}
[...]

protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
[...]

UserCache.cs

Код: Выделить всё

public class UserCache : INotifyPropertyChanged
{
private Collection  _allUsers = new Collection();
private UserModelView _current =  new UserModelView();

public event PropertyChangedEventHandler? PropertyChanged;

public ObservableCollection UsersShown { get; set; } = [];

public UserModelView Current
{
get => _current;
set
{
_current = value;
OnPropertyChanged(nameof(Current));
}
}

protected virtual void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}

private bool GetSomeUsersByFirstName()
{
var result = new List();
foreach (var item in _allUsers)
{
if (item.FirstName == Current.FirstName) result.Add(item);
}
UsersShown = new ObservableCollection(result);

// Feedback to the user, for what we have been looking for
Current = new UserModelView()
{
FirstName = Current.FirstName,
LastName = string.Empty,
PhoneNumber = string.Empty
};

return UsersShown.Any();
}

public bool Refresh()
{
UsersShown = new ObservableCollection(_allUsers);
Current = new UserModelView();
return UsersShown.Any();
}

[...]
UserViewModel.cs

Код: Выделить всё

using System.ComponentModel;
using UserWpfClient.Attributes;

namespace UserWpfClient.LocalData
{
public class UserModelView : INotifyPropertyChanged
{
private string _firstName = string.Empty;
private string _lastName = string.Empty;
private string _phoneNumber = string.Empty;

public event PropertyChangedEventHandler? PropertyChanged;

[ColumnName("Vorname")]
public string FirstName
{
get => _firstName ?? string.Empty;

set
{
_firstName = value;
OnPropertyChanged(nameof(FirstName));
}
}

[ColumnName("Nachname")]
public string LastName
{
get => _lastName ?? string.Empty;
set
{
_lastName = value;
OnPropertyChanged(nameof(LastName));
}
}

[ColumnName("Telefon")]
public string PhoneNumber
{
get => _phoneNumber ?? string.Empty;
set
{
_phoneNumber = value;
OnPropertyChanged(nameof(PhoneNumber));
}
}

protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Я нашел следующее: двусторонняя привязка в WPF
и двусторонняя привязка Wpf в списке.
И, как вы можете видеть, я изменил там классы (UserCache , ConnectedUserCache и UserModelView) соответственно.
Далее я буду следовать этому: https://learn.microsoft.com/en-us/dotne ... leproperty Но как это уменьшает количество шаблонов, я думаю, что мне все еще нужно понять основную причину моей проблемы, что означает гораздо лучшее понимание WPF и его событий.
MainWindow.xaml
Я предпринял несколько попыток с Mode=TwoWay и/или UpdateSourceTrigger=PropertyChanged.
UserCache.cs
Я попробовал это с INotifyPropertyChanged и без него.
Ожидание и то, что происходит на самом деле:

Я ожидаю, что если эти текстовые поля получили контент, это связанное свойство «Текущий» также имеет такое же содержимое, как и свойство «Текущий» внутри — и все это тоже наоборот.
Но произойдет следующее: если я напишите что-нибудь в одно из этих текстовых полей во время выполнения от имени пользователя, например. начните фильтровать пользователей по сетке данных (с привязкой к кешу), все работает нормально. Затем, после повторного отображения всех пользователей (что работает нормально) и ввода текстового поля по-прежнему отображается, когда я снова начинаю фильтрацию, оно должно работать так же, как и раньше, поскольку использует тот же код.
Но он снова не фильтрует. Мне нужно снова переписать текстовое поле. Таким образом, похоже, что границе нужен триггер обновления или, другими словами, граница кажется потерянной в этот конкретный момент.
Вопросы:
Итак , когда я записываю эти строки, мне интересно, не в том ли направлении ищу. Это проблема привязки? Или проблема кроется где-то в другом? Какие классы должны иметь INotifyChanged в моем примере?
Мой следующий шаг:
Если вы дадите мне несколько минут, в течение следующих дней я будут ли мои git-репозитории (WPF-Client и Backend-Service) общедоступными. Но, пожалуйста, не ждите чего-то идеального. Это всего лишь исследование для обучения.

Подробнее здесь: https://stackoverflow.com/questions/785 ... und-object
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»