안녕하세요! C#의 기본적인 기능이자 WPF에서 주로 사용하는 ObservableCollection 사용에 대해 질문이 있어서 글을 올립니다.
현재 WinUI3 를 이용해 프로젝트를 진행하고 있는데요, DB를 사용해서 값을 저장하고 그 저장된 값을 UI에서 계속적으로 데이터를 갱신 또는 누적시키는 부분에서 진도가 막혀 있는 상황입니다.
코드를 통해서 설명하자면
[Model]
// WinUI3 프로젝트는 Devexpress의 MVVM 모델을 사용합니다
// // DB 테이블 모델이 아닌 테이블의 데이터를 받아서 가공하기 위한 모델입니다.
public class ViewGroup : ViewModelBase
{
public int id { get; set; }
public string groupName { get; set; }
public ObservableCollection<ViewData > ViewDatas { get => GetValue<ObservableCollection<ViewData >>(); set => SetValue(value); }
}
public class ViewData : ViewModelBase
{
public int DataId { get; set; }
public int Number { get; set; }
public string CH_Name { get => GetValue<string>(); set => SetValue(value); }
public double? CH_Value { get => GetValue<double?>(); set => SetValue(value); }
public DateTime? WriteDate { get => GetValue<DateTime>(); set => SetValue(value); }
public ViewGroup ViewGroups { get; set; }
}
ViewGroup이라는 Model안에 DB에 저장된 데이터를 넣고, ObservableCollection ViewDatas를 이용하여 데이터들을 ObservableCollection 형태로 받아서 지속적으로 UI를 업데이트 시키는 코드를 구성하려고 했습니다.
여기서 변하는 UI는 ViewData의 들어오는 데이터들만 변하고, ViewGroup은 처음 할당 받으면 그 이상 변하지 않도록 코드를 작성하고 싶어요.
[XAML]
<ListView ItemsSource="{Binding ViewGroupsOB}">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding groupName}" />
<ListView ItemsSource="{Binding ViewData}">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding CH_Name}" />
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding CH_Value, Mode=TwoWay}" />
<TextBlock Text="{Binding WriteDate}" />
</StackPanel>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
[ViewModel]
public async void ViewDataReNew()
{
ViewGroupsOB = new ObservableCollection<ViewGroup>();
using (var newdbContext = new DataAccessEFCore())
{
var groupSelectionAll = newdbContext.SettingGroupConfigs
.Include(i => i.SettingSingleConfigs)
.ThenInclude(i2 => i2.DeviceChannel)
.ThenInclude(i3 => i3.DeviceDatas)
.ToObservableCollection();
HashSet<int> groupIds = new HashSet<int>(); // 새로운 Group 객체를 저장할 HasSet 생성
while (true)
{
foreach (var item in groupSelectionAll)
{
if (!groupIds.Contains(item.Id))
{
var ViewGroup = new ViewGroup
{
id = item.Id,
groupName = item.GroupName,
ViewData = new ObservableCollection<ViewData >()
};
groupIds.Add(item.Id);
foreach (var item2 in item.SettingSingleConfigs)
{
var ViewDATA = new ViewData
{
DataId= item2.Id,
Number = item2.TypeNumber,
CH_Name = item2.DeviceChannel.DeviceChannelName,
CH_Value = item2.DeviceChannel.DeviceDatas.GroupBy(g => g.DeviceChannels.DeviceChannelId)
.Select(s => s.OrderByDescending(o => o.WriteDate).First())
.FirstOrDefault(w => w.DeviceChannels != null).CH_Value,
ViewGroups = ViewGroup
};
// 데이터 지속적으로 업데이트 하는 코드
ViewDATA.CH_Value = item2.DeviceChannel.DeviceDatas.GroupBy(g => g.DeviceChannels.DeviceChannelId)
.Select(s => s.OrderByDescending(o => o.WriteDate).First())
.FirstOrDefault(w => w.DeviceChannels != null).CH_Value;
ViewDATA.WriteDate = item2.DeviceChannel.DeviceDatas.GroupBy(g => g.DeviceChannels.DeviceChannelId)
.Select(s => s.OrderByDescending(o => o.WriteDate).First())
.FirstOrDefault(w => w.DeviceChannels != null).WriteDate;
//여기부터 수정
ViewGroup.ViewChannelData.Add(ViewDATA);
}
if (ViewGroupsOB.Any(a => a.id != item.Id))
{
ViewGroupsOB.Add(ViewGroup);
}
else if (ViewGroupsOB.Count == 0)
{
ViewGroupsOB.Add(ViewGroup);
}
}
}
await Task.Delay(5000);
}
}
// ViewGroup의 ObservableCollection 선언
public ObservableCollection<ViewGroup> ViewGroupsOB { get => GetValue<ObservableCollection<ViewGroup>>(); set => SetValue(value); }
xaml에서 코드는 ViewGroup의 ObservableCollection을 ItemsSource로 Binding 하여 그 안에 ObservableCollection으로 데이터가 추가되는 ViewData를 실시간으로 업데이트 시키려고 구성하였습니다. 하지만 ViewModel에서 값을 집어 넣으면 처음 한 번은 값이 들어가지만 이후 ViewGroupOB의 값이 업데이트 되지 않아서 인지 제가 원했던 대로 동작을 하지 않더라고요 (당연한 얘기지만요…)
어떤 식으로 코드를 수정해야 {Binding ViewGroupOB} 를 통해서 UI 상에서 ViewData의 CH_Value를 계속해서 갱신시키고 차트와 같은 그래프를 그릴 수 있을까요…?