Я попытался изолировать свою проблему в очень простом (и работающем) проекте. Допустим, у меня есть простая модель с двумя полями, я настроил ее свойства и событие PropertyChanged
. Это упрощенная реализация моей модели. Обратите внимание, что последний метод просто получает новый клиентский объект из списка и возвращает его:
public class Clients : INotifyPropertyChanged
{
private long _Id = 0;
public long Id
{
get { return this._Id; }
set {
this._Id = value;
RaisePropertyChanged("Id");
}
}
private String _Name = string.Empty;
public String Name
{
get { return this._Name; }
set {
if (value is null)
this._Name = string.Empty;
else
this._Name = value;
RaisePropertyChanged("Name");
}
}
public event PropertyChangedEventHandler? PropertyChanged;
internal void RaisePropertyChanged(string name)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
// Let's say this is a populated list with 100 clients with different ids and names
public static List<Clients> clients = new List<Clients>();
// ...method for loading the list with DB data
public static Clients? LoadClient(long id)
{
return clients.FirstOrDefault(x => x.Id == id);
}
}
И у меня есть простой файл .xaml
для отображения данных одного клиента (идентификатор и имя). Каждый элемент управления пользовательского интерфейса имеет привязку к свойству клиента и триггеру обновления. У меня также есть две настроенные кнопки, которые будут вносить изменения в значения клиента:
<TextBox x:Name = "txtClientId" Text = "{Binding Id, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
</TextBox>
<TextBox x:Name = "txtClientName" Text = "{Binding Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
</TextBox>
<Button Name = "btnNext" Click = "btnNext_Click">Next</Button>
<Button Name = "btnRandom" Click = "btnRandom_Click">Random</Button>
Теперь давайте посмотрим на мой .xaml.cs
код. Вот инициализация и код для двух кнопок: одна из них просто изменяет свойства клиента непосредственно в объекте DataContext
, а другая просто назначает новый объект клиента клиенту DataContext
:
public partial class ClientsPage : Page
{
private Models.Clients? client = null;
public ClientsPage()
{
InitializeComponent();
// Load all clients data in Models.Clients.clients list...
client = new Models.Clients();
DataContext = client;
}
private void btnNext_Click(object sender, RoutedEventArgs e)
{
client = Models.Clients.LoadClient(client.Id + 1);
}
private void btnRandom_Click(object sender, RoutedEventArgs e)
{
Random random = new Random();
client.Id = random.Next(999);
client.Name = "RANDOM";
}
}
DataContext
, пользовательский интерфейс не меняется, поскольку событие PropertyChanged
не вызывается.Конечно, эту ситуацию можно решить, присвоив значения свойств вместо прямого назначения нового объекта:
private void btnNext_Click(object sender, RoutedEventArgs e)
{
Models.Clients newClient = Models.Clients.LoadClient(client.Id + 1);
this.client.Id = newClient.Id;
this.client.Name = newClient.Name;
}
Но это очень утомительно в реальном проекте с множеством моделей и методов, которые могут загружать/изменять объект с большим количеством полей. Я ищу простой/масштабируемый способ создания события PropertyChanged
, когда я назначаю новый объект переменной DataContext
. Если вам нужна более подробная информация о моем коде или у вас есть какие-либо вопросы, я буду рад задать их.
Лично я предпочитаю в первую очередь модель просмотра. Страница или пользовательский элемент управления будут созданы на основе модели представления, тогда это будет совершенно новая часть пользовательского интерфейса, когда свойство currentviewmodel будет изменено на новую модель представления. Не совсем уверен, что я следую тому, чего вы хотите достичь.
Если у вас есть новый объект, назначьте его также DataContext.
Это то, что я искал @GiladWaisel, с помощью которого я могу решить все свои проблемные ситуации, используя одно задание вместо того, чтобы назначать поле за полем (у меня есть объекты с +20 полями). Спасибо, чувак, если хочешь, можешь установить это как ответ.
@Энди, раньше у меня был внутренний void RaisePropertyChanged([CallerMemberName] String name = ""), но как вы думаете, где я мог бы вызвать этот метод с нулевым параметром, чтобы решить что-то, связанное с моей проблемой? Спасибо за замечание, но я думаю, что это ничего не решит для меня.
Новый экземпляр объекта создан, но не назначен DataContext. Требуется присвоение DataContext. Правильный код:
private void btnNext_Click(object sender, RoutedEventArgs e)
{
client = Models.Clients.LoadClient(client.Id + 1);
DataContext = client;
}
Знаете ли вы, что можно поднять свойство, повешенное с нулевым параметром, и это эквивалентно всем свойствам?