diff --git a/VECTO3GUI/Helper/Converter/JobEntrySelectedConverter.cs b/VECTO3GUI/Helper/Converter/JobEntrySelectedConverter.cs index e34b9b0f0693c7467e52640138414e004662b1fe..8e80432b9d017e47fd0b9c0637ff6132f6d146d6 100644 --- a/VECTO3GUI/Helper/Converter/JobEntrySelectedConverter.cs +++ b/VECTO3GUI/Helper/Converter/JobEntrySelectedConverter.cs @@ -11,8 +11,9 @@ namespace VECTO3GUI.Helper.Converter public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { - var jobEntry = (ViewModel.Impl.JobEntry)((ListViewItem)value)?.Content; - return jobEntry != null && jobEntry.Selected; + //var jobEntry = (ViewModel.Impl.JobEntry)((ListViewItem)value)?.Content; + //return jobEntry != null && jobEntry.Selected; + return value; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) diff --git a/VECTO3GUI/Helper/ObservableCollectionEx.cs b/VECTO3GUI/Helper/ObservableCollectionEx.cs new file mode 100644 index 0000000000000000000000000000000000000000..6253bc2a4ae2af40edaf3fb305b0231165b250bc --- /dev/null +++ b/VECTO3GUI/Helper/ObservableCollectionEx.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Collections.Specialized; +using System.ComponentModel; +using Castle.Core.Internal; + +namespace VECTO3GUI.Helper +{ + public class ObservableCollectionEx<T> : ObservableCollection<T> + { + public event PropertyChangedEventHandler CollectionItemChanged; + + public ObservableCollectionEx() + { + CollectionChanged += FullObservableCollectionCollectionChanged; + } + + public ObservableCollectionEx(IEnumerable<T> items) : this() + { + if (items == null) + return; + + foreach (var item in items) { + Add(item); + } + } + + public ObservableCollectionEx(IList<T> items) : this() + { + if(items.IsNullOrEmpty()) + return; + for (int i = 0; i < items.Count; i++) { + Add(items[i]); + } + } + + + private void FullObservableCollectionCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) + { + if (e.NewItems != null) + { + foreach (object item in e.NewItems) + { + ((INotifyPropertyChanged)item).PropertyChanged += ItemPropertyChanged; + } + } + if (e.OldItems != null) + { + foreach (object item in e.OldItems) + { + ((INotifyPropertyChanged)item).PropertyChanged -= ItemPropertyChanged; + } + } + } + + private void ItemPropertyChanged(object sender, PropertyChangedEventArgs e) + { + CollectionItemChanged?.Invoke(sender, e); + + var args = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, sender, sender, IndexOf((T)sender)); + OnCollectionChanged(args); + } + } +} diff --git a/VECTO3GUI/Model/JobListModel.cs b/VECTO3GUI/Model/JobListModel.cs new file mode 100644 index 0000000000000000000000000000000000000000..7043d7845c0fabc9579aad18cc78e937b8a966cd --- /dev/null +++ b/VECTO3GUI/Model/JobListModel.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections.Generic; +using System.IO; +using Castle.Core.Internal; +using VECTO3GUI.Helper; +using VECTO3GUI.ViewModel.Impl; + +namespace VECTO3GUI.Model +{ + + public class JobListEntry + { + public bool IsSelected { get; set; } + public string JobFilePath { get; set; } + } + + public class JobListModel + { + private const string ConfigFolderName = "Config"; + private const string JobListFileName = "JobList.txt"; + + private string _jobListFilePath = Path.Combine(".", ConfigFolderName, JobListFileName); + + public List<JobListEntry> JobList { get; set; } + + public JobListModel() + { + SetConfigFolder(); + LoadJobList(); + } + + private void SetConfigFolder() + { + if (!Directory.Exists($"./{ConfigFolderName}")) { + Directory.CreateDirectory($"{ConfigFolderName}"); + } + } + + private void LoadJobList() + { + var jobList = new List<JobListEntry>(); + if (File.Exists(_jobListFilePath)) + jobList = SerializeHelper.DeserializeToObject<List<JobListEntry>>(_jobListFilePath); + JobList = jobList; + } + + + public void SaveJobList(IList<JobEntry> jobEntries) + { + SetJobList(jobEntries); + SerializeHelper.SerializeToFile(_jobListFilePath, JobList); + } + + private void SetJobList(IList<JobEntry> jobEntries) + { + if (jobEntries.IsNullOrEmpty()) + return; + + JobList = new List<JobListEntry>(); + + for (int i = 0; i < jobEntries.Count; i++) { + JobList.Add + ( + new JobListEntry + { + IsSelected = jobEntries[i].Selected, + JobFilePath = jobEntries[i].JobEntryFilePath + } + ); + } + } + + public IList<JobEntry> GetJobEntries() + { + var jobEntries = new List<JobEntry>(); + + if (JobList.IsNullOrEmpty()) + return jobEntries; + + for (int i = 0; i < JobList.Count; i++) { + var jobEntry = SerializeHelper.DeserializeToObject<JobEntry>(JobList[i].JobFilePath); + if(jobEntry != null) + jobEntries.Add(jobEntry); + } + + return jobEntries; + } + } +} diff --git a/VECTO3GUI/VECTO3GUI.csproj b/VECTO3GUI/VECTO3GUI.csproj index 1e1f5baaa55ed01cfe8dc05828b3dd64c49c6d58..085ca6576d3f1ce60b05273d13eebc9075a5e753 100644 --- a/VECTO3GUI/VECTO3GUI.csproj +++ b/VECTO3GUI/VECTO3GUI.csproj @@ -166,11 +166,13 @@ <Compile Include="Helper\Converter\EnumConverter.cs" /> <Compile Include="Helper\Extension.cs" /> <Compile Include="Helper\FileDialogHelper.cs" /> + <Compile Include="Helper\ObservableCollectionEx.cs" /> <Compile Include="Helper\OutputWindowHelper.cs" /> <Compile Include="Helper\Converter\SaveButtonLabelConverter.cs" /> <Compile Include="Helper\SerializeHelper.cs" /> <Compile Include="Helper\ViewModelBase.cs" /> <Compile Include="Model\InterfacesImpl.cs" /> + <Compile Include="Model\JobListModel.cs" /> <Compile Include="Model\SettingsModel.cs" /> <Compile Include="Model\TempDataObject\AirdragComponentData.cs" /> <Compile Include="Model\TempDataObject\AuxiliariesBusComponentData.cs" /> diff --git a/VECTO3GUI/ViewModel/Impl/JoblistViewModel.cs b/VECTO3GUI/ViewModel/Impl/JoblistViewModel.cs index 20b071475785de74d7822d5ea1acf4819abfd1cd..fc1bd8c6c4fe23f1aa0acf18b7902ed865bef743 100644 --- a/VECTO3GUI/ViewModel/Impl/JoblistViewModel.cs +++ b/VECTO3GUI/ViewModel/Impl/JoblistViewModel.cs @@ -1,27 +1,20 @@ using System; using System.Collections; using System.Collections.ObjectModel; +using System.Collections.Specialized; +using System.ComponentModel; using System.IO; using System.Linq; using System.Windows; -using System.Windows.Controls; -using System.Windows.Documents; using System.Windows.Input; using Ninject; -using Ninject.Parameters; -using TUGraz.VectoCommon.Exceptions; using TUGraz.VectoCommon.InputData; using TUGraz.VectoCore.Configuration; -using TUGraz.VectoCore.InputData.FileIO.JSON; using TUGraz.VectoCore.InputData.FileIO.XML; -using TUGraz.VectoCore.InputData.FileIO.XML.Declaration; -using TUGraz.VectoCore.InputData.FileIO.XML.Engineering; -using TUGraz.VectoCore.Utils; using VECTO3GUI.Util; using VECTO3GUI.ViewModel.Interfaces; using System.Xml; using System.Xml.Linq; -using Microsoft.WindowsAPICodePack.Shell.PropertySystem; using TUGraz.VectoCommon.Resources; using TUGraz.VectoCore.InputData.FileIO.XML.Declaration.DataProvider; using VECTO3GUI.Helper; @@ -35,11 +28,12 @@ namespace VECTO3GUI.ViewModel.Impl { #region Members - protected readonly ObservableCollection<JobEntry> _jobs = new ObservableCollection<JobEntry>(); + protected ObservableCollectionEx<JobEntry> _jobs; protected readonly ObservableCollection<MessageEntry> _messages = new ObservableCollection<MessageEntry>(); private readonly SettingsModel _settings; private JobEntry _selectedJobEntry; + private JobListModel _jobListModel; #endregion @@ -67,9 +61,10 @@ namespace VECTO3GUI.ViewModel.Impl set { SetProperty(ref _selectedJobEntry, value); } } - public ObservableCollection<JobEntry> Jobs + public ObservableCollectionEx<JobEntry> Jobs { get { return _jobs; } + set { SetProperty(ref _jobs, value); } } public ObservableCollection<MessageEntry> Messages @@ -88,23 +83,27 @@ namespace VECTO3GUI.ViewModel.Impl private void SetJobEntries() { - var xmlFiles = Directory.GetFiles(_settings.XmlFilePathFolder, "*.xml"); - for (int i = 0; i < xmlFiles.Length; i++) { - AddJobEntry(xmlFiles[i]); - } + _jobListModel = new JobListModel(); + _jobs = new ObservableCollectionEx<JobEntry>(_jobListModel.GetJobEntries()); + _jobs.CollectionChanged += JobsCollectionChanged; + _jobs.CollectionItemChanged += JobItemChanged; } - private void AddJobEntry(string jobFile) + private void JobItemChanged(object sender, PropertyChangedEventArgs e) { - _jobs.Add(new JobEntry() - { - FirstFilePath = jobFile, - Selected = false, - Sorting = _jobs.Count - }); + _jobListModel.SaveJobList(_jobs); } - + private void JobsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) + { + switch (e.Action) { + case NotifyCollectionChangedAction.Add: + case NotifyCollectionChangedAction.Remove: + _jobListModel.SaveJobList(_jobs); + break; + } + } + #region Implementation IJoblistViewModel public ICommand RemoveJob diff --git a/VECTO3GUI/ViewModel/Interfaces/IJoblistViewModel.cs b/VECTO3GUI/ViewModel/Interfaces/IJoblistViewModel.cs index 4c0f44b9c7bda3d33d2b5f5f1db8e14c78c3000c..7b1707d00babdf0ade928995dfd4c38644e8b0df 100644 --- a/VECTO3GUI/ViewModel/Interfaces/IJoblistViewModel.cs +++ b/VECTO3GUI/ViewModel/Interfaces/IJoblistViewModel.cs @@ -1,12 +1,13 @@ using System.Collections.ObjectModel; using System.Windows.Input; +using VECTO3GUI.Helper; using VECTO3GUI.ViewModel.Impl; namespace VECTO3GUI.ViewModel.Interfaces { public interface IJoblistViewModel : IMainView { - ObservableCollection<JobEntry> Jobs { get; } + ObservableCollectionEx<JobEntry> Jobs { get; } ObservableCollection<MessageEntry> Messages { get; } ICommand AddBusJob { get; } ICommand AddJob { get; } diff --git a/VECTO3GUI/Views/JoblistView.xaml b/VECTO3GUI/Views/JoblistView.xaml index 2ed97f2810b85c7ad9d57530bb94c2eebe5daf6b..8ef3a4673310b623b799d0eb39ecec2da17d9653 100644 --- a/VECTO3GUI/Views/JoblistView.xaml +++ b/VECTO3GUI/Views/JoblistView.xaml @@ -9,6 +9,7 @@ xmlns:interfaces="clr-namespace:VECTO3GUI.ViewModel.Interfaces" xmlns:views="clr-namespace:VECTO3GUI.Views" xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls" + xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="600" d:DataContext="{d:DesignInstance Type=impl:JoblistViewModel, IsDesignTimeCreatable=False}"> @@ -19,7 +20,7 @@ <Grid> <Grid.ColumnDefinitions> - <ColumnDefinition Width="30"/> + <ColumnDefinition Width="80"/> <ColumnDefinition/> <ColumnDefinition Width="80"/> </Grid.ColumnDefinitions> @@ -32,7 +33,12 @@ <Grid Grid.Row="1" Grid.Column="0"> - <!--<Button VerticalAlignment="Top" Margin="0,10,0,0"/>--> + <Button VerticalAlignment="Top" Margin="10,40,0,0"> + <StackPanel Orientation="Horizontal"> + <iconPacks:PackIconModern Width="20" Height="15" Kind="ControlPlay" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="Green"/> + <TextBlock Text="Start " /> + </StackPanel> + </Button> </Grid> <Grid Grid.Row="1" Grid.Column="1" Margin="10"> @@ -40,7 +46,7 @@ <DataGrid ItemsSource="{Binding Jobs}" SelectedValue="{Binding DataContext.SelectedJobEntry, RelativeSource={RelativeSource AncestorType=views:JoblistView}}" Style="{DynamicResource AzureDataGrid}" BorderThickness="1" CanUserAddRows="False" AutoGenerateColumns="False" SelectionUnit="FullRow" - IsReadOnly="True" HeadersVisibility="All" RowHeaderWidth="5" > + IsReadOnly="False" HeadersVisibility="All" RowHeaderWidth="5" > <DataGrid.Resources> <ContextMenu x:Key="RowMenu"> @@ -61,11 +67,12 @@ </DataGrid.ContextMenu> <DataGrid.Columns> - <DataGridTextColumn Header="File Path" Binding="{Binding FirstFilePath}" > + <DataGridCheckBoxColumn Binding="{Binding Selected, UpdateSourceTrigger=PropertyChanged}" /> + <DataGridTextColumn Header="File Path" Binding="{Binding JobEntryFilePath}" IsReadOnly="True"> <DataGridTextColumn.CellStyle> <Style TargetType= "{x:Type DataGridCell}" BasedOn="{StaticResource MetroDataGridCell}" > <Setter Property="ContextMenu" Value="{StaticResource RowMenu}"/> - <Setter Property="HorizontalAlignment" Value="Stretch"></Setter> + <Setter Property="HorizontalAlignment" Value="Stretch"/> </Style> </DataGridTextColumn.CellStyle> </DataGridTextColumn> @@ -95,14 +102,7 @@ </DataGrid.Columns> </DataGrid> - </Grid> </Grid> - - - - - - </UserControl>