我写了一些代码来读取CSV文件并将其转换为DateTable。在下一步中,它会读取DataTable以获取特定值。这些值保存在对象中,此对象将添加到ObserableCollection。
XAML:
<ListView ItemsSource="{Binding ProdOrderView}" x:Name="listView" Margin="9,70,112,34" AlternationCount="2" FontSize="14">
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Style.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="0">
<Setter Property="Background" Value="White" />
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Background" Value="LightGray" />
</Trigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
<ListView.View >
<GridView >
<GridViewColumn Header="Fauf" Width="Auto">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Fauf}" TextAlignment="Right" Name="fauf"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Prod-Start" Width="Auto">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Start}" TextAlignment="Center" Name="start"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Rück- 
stand" Width="Auto">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock x:Name="inRueck" Text="{Binding InRueck}" TextAlignment="Center" />
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding InRueck, Converter={StaticResource ColorConverterInRueck}}" Value="delay">
<Setter TargetName="inRueck" Property="Background" Value="Red" />
</DataTrigger>
<DataTrigger Binding="{Binding InRueck, Converter={StaticResource ColorConverterInRueck}}" Value="inTime">
<Setter TargetName="inRueck" Property="Background" Value="Green" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="heute" Width="Auto" >
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock x:Name="Heute" Text="{Binding Heute}" TextAlignment="Center" />
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Heute}" Value="X">
<Setter TargetName="Heute" Property="Background" Value="CornflowerBlue" />
</DataTrigger>
<DataTrigger Binding="{Binding Heute}" Value="?">
<Setter TargetName="Heute" Property="Foreground" Value="DarkViolet" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="morgen" Width="Auto" >
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Morgen}" TextAlignment="Center" Name="Morgen"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="+2" Width="Auto" >
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Uebermorgen}" TextAlignment="Center" Name="Uebermorgen"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
...
</GridView>
</ListView.View>
</ListView>
代码隐藏:
public MainWindow()
{
InitializeComponent();
MainViewModel mvm = new MainViewModel(filepath,pline);
listView.ItemSource = mvm.ProdOrderView;
}
MainViewModel:
class MainViewModel
{
#region Private Felder
private ObservableCollection<ProductionOrder> _prodOrderList;
private ListCollectionView _prodOrderView;
#endregion
#region Konstruktor
public MainViewModel(string filepath, string pline)
{
// ProductionOrderliste initialisieren
_prodOrderList = new ObservableCollection<ProductionOrder>();
_prodOrderList.Clear();
fillObject(filepath, pline, ref _prodOrderList);
// ListCollectionView initialisieren
_prodOrderView = new ListCollectionView(_prodOrderList);
}
#endregion
#region Öffentliche Eigenschaften
public ListCollectionView ProdOrderView
{
get { return _prodOrderView; }
}
#endregion
#region ConvertCSVtoDataTabble
public DataTable ConvertCSVtoDataTable(string filename)
{
//DataTable anlegen
DataTable dataTable = new DataTable();
dataTable.Columns.Clear();
dataTable.Rows.Clear();
dataTable.Clear();
try
{
//Filestream anlegen, dadurch kann Datei auch gelesen werden, wenn sie geöffnet ist
FileStream logFileStream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
using (StreamReader streamReader = new StreamReader(logFileStream))
{
//Array mit allen Überschriften
string[] headers = streamReader.ReadLine().Split(';');
//Schleife durchläuft das Array headers
foreach (string header in headers)
{
//Der DataTable wird eine Spalte mit dem aktuellen header (Überschrift) hinzugefügt.
dataTable.Columns.Add(header);
}
//Schleife, die so lange gültig ist bis das Ende des Streams erreicht wurde
while (!streamReader.EndOfStream)
{
//Array mit allen Zeilen füllen
string[] rows = streamReader.ReadLine().Split(';');
//Der DataTable wird die Zeile mit dem aktuellen Werten der Zeile hinzugefügt.
dataTable.Rows.Add(rows);
}
//StreamReader wird geschlossen
streamReader.Close();
//Filestream wird geschlossen
logFileStream.Close();
}
}
catch(IndexOutOfRangeException e)
{
Console.WriteLine("Fehlercode:" + e);
ConvertCSVtoDataTable(filename);
}
//gefüllte DataTable wird zurückgegeben
return dataTable;
}
#endregion
#region fillObbject
public void fillObject(string filepath, string plinie, ref ObservableCollection<ProductionOrder> liste)
{
//DataTable res = new DataTable();
//res.Columns.Clear();
//res.Rows.Clear();
//res.Clear();
string emptyField = "\" \"";
DataTable res = ConvertCSVtoDataTable(filepath);
try
{
foreach (DataRow row in res.Rows) // Loop over the rows.
{
if (row["AFKO_PLTXT"].ToString() == plinie)
{
////Objekt anlegen
ProductionOrder order = new ProductionOrder();
//#region Prüft ob Sammelhinweis vorhanden
string sammel = "";
Queue<string> queue = new Queue<string>();
if (res.Columns.Contains("ZZTAG_MO"))
{
//Montag
if (row["ZZTAG_MO"].ToString() == "X")
{
sammel = "MO";
queue.Enqueue(sammel);
}
//Dienstag
if (row["ZZTAG_DI"].ToString() == "X")
{
sammel = "DI";
queue.Enqueue(sammel);
}
//Mittwoch
if (row["ZZTAG_MI"].ToString() == "X")
{
sammel = "MI";
queue.Enqueue(sammel);
}
//Donnerstag
if (row["ZZTAG_DO"].ToString() == "X")
{
sammel = "DO";
queue.Enqueue(sammel);
}
//Freitag
if (row["ZZTAG_FR"].ToString() == "X")
{
sammel = "FR";
queue.Enqueue(sammel);
}
//Samstag
if (row["ZZTAG_SA"].ToString() == "X")
{
sammel = "SA";
queue.Enqueue(sammel);
}
//Sonntag
if (row["ZZTAG_SO"].ToString() == "X")
{
sammel = "SO";
queue.Enqueue(sammel);
}
}
// string sammelList wird zusammengesetzt
string sammelList = "";
if (queue.Count > 0)
{
sammelList = "/";
while (queue.Count > 0)
{
if (queue.Count > 1)
sammelList += queue.Dequeue() + "+";
else
{
sammelList += queue.Dequeue();
}
}
}
#endregion
//das Objekt wird mit den entsprechenden Werten gefüllt
order.Fauf = row["EXTRA_APO"].ToString();
order.Start = row["GSTRP_KO"].ToString();
order.Vorgang = row["LTXA1_AFVC"].ToString();
order.Kundenauftrag = row["KDAUF_FK"].ToString() + sammelList;
order.Material = row["MATNR_PO"].ToString();
order.Materialbezeichnung = row["MAKTX_MAKT"].ToString();
order.Menge = row["AFKO_GAMNG"].ToString();
order.WE_Menge = row["WEMNG_PO"].ToString();
order.Ende = row["GLTRP_KO"].ToString();
order.Notiz = row["NOTIZ_TEXT"].ToString();
order.Ladedatum = row["LDDAT_VBEP"].ToString();
order.Dauer = row["FAUFDAUER_REST_KO"].ToString();
//führende Nullen werden entfernt falls vorhanden
order.Kundenauftrag = order.Kundenauftrag.TrimStart('0');
order.Material = order.Material.TrimStart('0');
if (order.Menge.Contains(","))
{
order.Menge = order.Menge.Remove(order.Menge.IndexOf(@","));
}
if (order.WE_Menge.Contains(","))
{
order.WE_Menge = order.WE_Menge.Remove(order.WE_Menge.IndexOf(@","));
}
order.Heute = "";
order.Morgen = "";
order.Uebermorgen = "";
order.Plus3 = "";
order.Plus4 = "";
order.Plus5 = "";
string inKlaerung = "";
//konvertiert String zu Datetime
DateTime newStartDate = convertDateTime(order.Start);
order.Start = newStartDate.ToString("dd.MM.yyyy");
//Berechne Verzug in Tagen
int verzugTage = (DateTime.Today - newStartDate).Days;
order.InRueck = verzugTage.ToString();
//konvertiert String zu Datetime
var newLadedatum = convertDateTime(order.Ladedatum);
order.Ladedatum = newLadedatum.ToString("dd.MM.yyyy");
if (inKlaerung != emptyField)
{
//X in der Spalte setzen, an dem Tag wo es gefertigt wird
if (verzugTage >= 0)
{
order.Heute = "X";
}
else
{
switch (verzugTage)
{
case -1:
order.Morgen = "X";
break;
case -2:
order.Uebermorgen = "X";
break;
case -3:
order.Plus3 = "X";
break;
case -4:
order.Plus4 = "X";
break;
case -5:
order.Plus5 = "X";
break;
default:
break;
}
}
}
else
{
order.Heute = "?";
}
try
{
//konvertiert String zu Datetime
var newEndDate = convertDateTime(order.Ende);
order.Ende = newEndDate.ToString("dd.MM.yyyy");
}
catch (FormatException e)
{
Console.WriteLine("Fehlercode:" + e);
order.Ende = "Fehler";
}
// Prüft ob Vorgang leer ist
if (order.Vorgang == emptyField)
{
order.Vorgang = "";
}
//Prüft ob Notiz leer ist
if (order.Notiz == emptyField)
{
order.Notiz = "";
}
//Prüft ob Dauer leer ist
if (order.Dauer == emptyField)
{
order.Dauer = "";
}
liste.Add(order);
}
}
}
catch (ArgumentException e)
{
Console.WriteLine("Fehlercode:" + e);
}
}
// #endregion
#region convertDateTime
public DateTime convertDateTime(string date)
{
//konvertiert String zu Datetime
DateTime newDate = DateTime.ParseExact(date,
"yyyyMMdd",
System.Globalization.CultureInfo.InvariantCulture);
return newDate;
}
#endregion
}
}
当我每分钟加载CSV文件时,对象的数量会急剧增加。垃圾收集器不会清除所有旧对象。任何人都可以帮我找到这个问题吗?
答案 0 :(得分:0)
我的猜测是你的问题是你不需要使用数据表。
dataTable是一个非常复杂的项目,基本上是基于代码的数据库表,因此使用MarshalByValueComponent
,它告诉您这不能自动GC编辑,因此要求您在完成使用后调用Dispose。 (调用Dispose告诉它清理其非托管代码的链接并可供垃圾收集器使用)。
你有两个选项可以触发处理对Dispose函数或Using(){}语句的简单调用
你需要为所有非托管的类(包括StreamReader和FileStream)执行此操作
因为你没有使用数据表作为数据表,只是一张表然后我会建议完全删除它而只是解析你的文本文件
编辑:
这里是MVVM文件解析器的快速而肮脏的模型
XAML:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication1"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:FileViewModel x:Name="vm" />
</Window.DataContext>
<DockPanel >
<DockPanel DockPanel.Dock="Top">
<Button DockPanel.Dock="Right" Click="Button_Click">Read</Button>
<TextBox Text="{Binding File}" />
</DockPanel>
<ListView ItemsSource="{Binding ItemCollection}">
<ListView.View>
<GridView>
<GridViewColumn DisplayMemberBinding="{Binding field1}" Header="Feild1"/>
<GridViewColumn DisplayMemberBinding="{Binding field2}" Header="Field2"/>
<GridViewColumn DisplayMemberBinding="{Binding field3}" Header="Field3"/>
<GridViewColumn DisplayMemberBinding="{Binding field4}" Header="Field4"/>
</GridView>
</ListView.View>
</ListView>
</DockPanel>
</Window>
代码背后:
public partial class MainWindow : Window
{
public MainWindow()
{
this.InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
vm.ReadFile();
}
}
文件阅读器
public class FileViewModel : INotifyPropertyChanged
{
private string _File;
public string File
{
get { return _File; }
set
{
_File = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("File"));
}
}
public ObservableCollection<ItemModel> ItemCollection { get; } = new ObservableCollection<ItemModel>();
public event PropertyChangedEventHandler PropertyChanged;
public void ReadFile()
{
ItemCollection.Clear();
using (StreamReader reader = new StreamReader(File))
{
var header = reader.ReadLine();
while(!reader.EndOfStream)
{
var data = reader.ReadLine();
var item = ItemModel.Create(header, data, ',');
ItemCollection.Add(item);
}
}
}
}
项目解析器
public class ItemModel
{
public static ItemModel Create(string colstr, string datastr, char delimiter)
{
var cols = colstr.Split(delimiter);
var data = datastr.Split(delimiter);
var item = new ItemModel();
item.field1 = int.Parse(GetValue(cols, data, "field1"));
item.field2 = DateTime.Parse(GetValue(cols, data, "field2"));
item.field3 = GetValue(cols, data, "field3");
item.field4 = double.Parse(GetValue(cols, data, "field4"));
return item;
}
public static string GetValue(string[] cols, string[] data, string colName)
{
var colid = Array.IndexOf(cols, colName);
if (colid == -1)
return null;
else
return data[colid];
}
public int field1 { get; set; }
public DateTime field2 { get; set; }
public string field3 { get; set; }
public double field4 { get; set; }
}
使用的演示文件
field2,field1,field4,field3
01-Jan-16,1,1.1,a
02-Jan-16,2,2.2,b
03-Jan-16,3,3.3,c
04-Jan-16,4,4.4,d