I have been trying for some hours to get my ListView with ObservableCollection to work. However, no luck. I also read through some posts in here and there and try to match and still no good. Please give me pointer on where it went wrong.
Basically, what I am trying to do is split logic from VM to Helper class. And the logic in this class will update the data but VM does not aware of it.
My problem is in copying file function, the job status does not change the view data. I tried Messenger.Default.Send (from the helper) and Messenger register (in VM), to accept the changes, still no luck.
I am using MVVM Light, WPF, C# by the way.
Here is my code for Model.
public class MyFile : ViewModelBase
{
public string fullFileName { get; set; }
public string fileName { get; set; }
private string _jobStatus;
public string jobStatus
{
get { return _jobStatus; }
set { Set(ref _jobStatus, value); }
}
}
Here is my code for Helper.
class FileHelper
{
public List<MyFile> GetFileName(string dir)
{
List<MyFile> lstFiles = new List<MyFile>();
foreach (var file in (new DirectoryInfo(dir).GetFiles()))
{
if (file.Name.ToLower().Contains("xls") && !file.Name.Contains("~$"))
lstFiles.Add(new MyFile() { fullFileName = file.FullName, fileName = file.Name, jobStatus = "-" });
}
return lstFiles;
}
public bool CopyFiles(string destDir, List<MyFile> lstFiles)
{
try
{
int counter = 0;
foreach (MyFile f in lstFiles)
{
f.jobStatus = "Copying";
File.Copy(f.fullFileName, Path.Combine(destDir, f.fileName),true);
f.jobStatus = "Finished";
counter += 1;
Console.WriteLine("M: " + DateTime.Now.ToString("hh:mm:ss") + " " + counter);
Messenger.Default.Send(counter, "MODEL");
}
return true;
}
catch (Exception e)
{
Console.WriteLine("Error: " + e.Message);
return false;
}
}
}
Here is my code for VM.
public class MainViewModel : ViewModelBase
{
public ICommand CmdJob { get; private set; }
private ObservableCollection<MyFile> fileList;
public ObservableCollection<MyFile> FileList
{
get { return fileList; }
set { Set(ref fileList, value); }
}
private string counter;
public string Counter
{
get { return counter; }
set { Set(ref counter, value); }
}
public MainViewModel()
{
Messenger.Default.Register<int>(this, "MODEL", UpdateCounter);
CmdJob = new RelayCommand<object>(Action_Job);
Counter = "0";
}
private void UpdateCounter(int bgCounter)
{
Counter = bgCounter.ToString();
RaisePropertyChanged("FileList");
Console.WriteLine("VM: " + DateTime.Now.ToString("hh:mm:ss") + " " + Counter);
}
private void Action_Job(object tag)
{
if (tag == null || string.IsNullOrEmpty(tag.ToString()))
return;
switch (tag.ToString())
{
case "GET": GetFile(); break;
case "COPY": CopyFile(); break;
}
}
private void GetFile()
{
Counter = "0";
List<MyFile> myFs = new FileHelper().GetFileName(@"C:\Test\Original\");
FileList = new ObservableCollection<MyFile>(myFs);
}
private void CopyFile()
{
if (new FileHelper().CopyFiles(@"C:\Test\Destination\", fileList.ToList()))
Messenger.Default.Send("Files copying finished", "VM");
else
Messenger.Default.Send("Files copying failed", "VM");
}
}
And here is my XAML.
<ListView Grid.Row="0" Grid.Column="0" ItemsSource="{Binding FileList}" Margin="5,5,0,5" HorizontalAlignment="Left" VerticalAlignment="Stretch" ScrollViewer.VerticalScrollBarVisibility="Visible">
<ListView.View>
<GridView>
<GridViewColumn Header="File Name" Width="170" DisplayMemberBinding="{Binding fileName}" />
<GridViewColumn Header="Status" Width="170" DisplayMemberBinding="{Binding jobStatus}" >
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
<StackPanel Grid.Row="0" Grid.Column="1" Orientation="Vertical">
<Button Content="Get file list" Tag="GET" Command="{Binding CmdJob}" CommandParameter="{Binding RelativeSource={RelativeSource Self}, Path=Tag}" Width="80" Height="25" Margin="0,50,0,50"/>
<Button Content="Copy file" Tag="COPY" Command="{Binding CmdJob}" CommandParameter="{Binding RelativeSource={RelativeSource Self}, Path=Tag}" Width="80" Height="25" />
<Label Content="{Binding Counter}" HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" Height="25" FontWeight="Bold" Foreground="Red" Margin="0,50,0,0"/>
</StackPanel>
I read through some posts, it said for "change", ObservableCollection will not reflect the changes to View. So, I follow those posts solution (to use Notify change in Model class), not working for me.
For me, my individual file is a big file size, so I can see there is no update on my VM.
If you test with small file size, you will not see the difference.
I tried to use Messenger method, it also not updating on View but my VM can accept incoming message with no issue.