我已经查看有关此问题的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>
您应该设置现有对象的 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
变量设置为对传递给 UpdateList
方法的新ModelObj
对象的引用。这不会更新the
模型对象集合中的对象的 Timer
属性。
testObj = modelObj
没有效果。您只需将值放入变量即可。叫
if (testObj != null)
{
ModelObjects.Replace(testObj,modelObj)
}
else
{
ModelObjects.Add(modelObj);
}
如果您替换整个对象,则根本不需要实现 INotifyPropertyChanged