我一直在关注这个问题的Stackoverflow帖子两天了,我似乎无法理解为什么我的代码无效
当我更改ObservableCollection
中的项目时,我似乎无法在我的UI中更新数据网格。
我知道ObservableCollection
如果其中的项目发生变化,则不会触发PropertyChanged
事件。
似乎其他人已成功完成此操作,方法是将INotifyPropertyChanged
添加到模型中,并在更改属性时调用OnPropertyChanged
。我已经实现了这一点,并且我已经检查了PropertyChanged
事件是否已经结束。
在向集合添加新项目时,UI会更新。
我意识到这可能是一个线程问题,但我真的不明白如何检查或修复它。
我对编程很新,并试图围绕MVVM。
有什么建议吗?
型号:
public class ModelObj : INotifyPropertyChanged
{
public string Name { get; set; }
public string IpAddress { get; set; }
private DateTime timer;
public DateTime Timer
{
get { return timer; }
set
{
timer = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
视图模型:
public class MainViewModel : ViewModelBase
{
public ObservableCollection<ModelObj> ModelObjects { get; } = new ObservableCollection<ModelObj>();
private IUdpDataService _udpDataService;
public MainViewModel(IUdpDataService udpDataService)
{
_udpDataService = udpDataService;
}
public void StartUdpDataService()
{
_udpDataService.StartBroadCasting();
_udpDataService.ReceivedDataEvent += ParseReceivedData;
}
private void ParseReceivedData(string receivedData)
{
// This object contains all the information in the received data packet.
UdpPacket udpPacket = new UdpPacket(receivedData);
// This object only contains the object name, IpAddress and a time variable.
ModelObj modelObj = new ModelObj
{
Name = udpPacket.Name,
IpAddress = udpPacket.IpEthernet,
Timer = DateTime.Now,
};
App.Current.Dispatcher.Invoke((Action)delegate
{
UpdateList(modelObj);
});
}
private void UpdateList(ModelObj modelObj)
{
var testObj = ModelObjects.FirstOrDefault(x => x.Name == modelObj.Name);
if (testObj != null)
{
testObj = modelObj
}
else
{
ModelObjects.Add(modelObj);
testObj = modelObj;
}
}
}
查看:
public partial class MainWindow : Window
{
private MainViewModel _viewModel;
public MainWindow(MainViewModel viewModel)
{
InitializeComponent();
_viewModel = viewModel;
DataContext = _viewModel;
Loaded += MainWindow_Loaded;
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
_viewModel.StartUdpDataService();
}
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
Settings.Default.Save();
base.OnClosing(e);
}
}
XAML:
<DataGrid Grid.Row="0" ItemsSource="{Binding Path=ModelObjects}"
IsReadOnly="True"
Background="white"
RowHeaderWidth ="0"
AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding Name}" Width="auto" MinWidth="150"/>
<DataGridTextColumn Header="IP address" Binding="{Binding IpAddress}" Width="*"/>
<DataGridTextColumn Header="Timer" Binding="{Binding Timer, UpdateSourceTrigger=PropertyChanged}" Width="*"/>
</DataGrid.Columns>
</DataGrid>
答案 0 :(得分:1)
您应该设置现有对象的Timer
属性:
private void UpdateList(ModelObj modelObj)
{
var testObj = ModelObjects.FirstOrDefault(x => x.Name == modelObj.Name);
if (testObj != null)
{
testObj.Timer = modelObj.Timer
}
else
{
ModelObjects.Add(modelObj);
}
}
您当前正在获取对现有对象的引用,然后将包含此引用的testObj
变量设置为对传递给ModelObj
方法的新UpdateList
对象的引用。这不会更新Timer
ModelObjects集合中对象的the
属性。
答案 1 :(得分:0)
testObj = modelObj
没有效果。您只需将值放入变量即可。致电
if (testObj != null)
{
ModelObjects.Replace(testObj,modelObj)
}
else
{
ModelObjects.Add(modelObj);
}
如果你替换整个对象,根本不需要实现INotifyPropertyChanged