###Purpose of the application**
Purpose of the application**
##Structure
Structure
###User controls
Stack Exchange network consists of 183 Q&A communities including Stack Overflow, the largest, most trusted online community for developers to learn, share their knowledge, and build their careers.
Visit Stack ExchangeTeams
Learn more about Teams###Purpose of the application**
##Structure
###User controls
###Purpose of the application**
##Structure
###User controls
###Purpose of the application**
##Structure
###User controls
To keep things simpler and more reusable, I have created a user control for uploader section, as this will repeat three times - it has got:.
As a result, this user control has got 17 dependency properties and 4 events:
Full XAML on dotnetfiddle, click on the View tab
Now, in my MainWindow.xaml file, apart from crap like status bar and menu bar, I need to define three UploaderControls. And this is where it starts being pretty monstrous (especially if I were to have e.g. 10 types of files to upload) For each of the controls I need a separate set of properties to be bound.
Apart from that there's a bunch of miscellaneous props for visbility, auto-uplad and event handlers. I am not really concerned about those.
<controls:UploaderControl ControlHeader="Workflow plugin"
ContentVisibility="{Binding ElementName=ThisUc, Path=WorkflowUploaderVisibility}"
HideButtonClick="OnHideButtonClick"
CurrentProvidedPath="{Binding ElementName=ThisUc, Path=CurrentWorkflowPluginPath, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
PreviousPathsCollection="{Binding ElementName=ThisUc, Path=PreviousWorkflowPluginPathsCollection}"
CurrentProvidedConfigPath="{Binding ElementName=ThisUc, Path=CurrentWorkflowPluginConfigPath, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
PreviousConfigPathsCollection="{Binding ElementName=ThisUc, Path=PreviousWorkflowPluginConfigPathsCollection}"
DockPanel.Dock="Top"
OpenServerFolder="UploaderControl_OnOpenServerFolder"
AutoUploadAfterBuild="{Binding ElementName=ThisUc,Path=WorkflowAutoUpload,Mode=TwoWay}"
LocalLastModified="{Binding ElementName=ThisUc, Path=LocalWorkflowPluginLastModified}"
LocalLastModifiedBrush="{Binding ElementName=ThisUc, Path=LocalWorkflowPluginLastModifiedBrush}"
ServerLastModified="{Binding ElementName=ThisUc, Path=ServerWorkflowPluginLastModified}"
ServerLastModifiedBrush="{Binding ElementName=ThisUc, Path=ServerWorkflowPluginLastModifiedBrush}"
LocalConfigLastModified="{Binding ElementName=ThisUc, Path=LocalWorkflowPluginConfigLastModified}"
LocalConfigLastModifiedBrush="{Binding ElementName=ThisUc, Path=LocalWorkflowConfigLastModifiedBrush}"
ServerConfigLastModified="{Binding ElementName=ThisUc, Path=ServerWorkflowPluginConfigLastModified}"
ServerConfigLastModifiedBrush="{Binding ElementName=ThisUc, Path=ServerWorkflowConfigLastModifiedBrush}"
UploadPluginClick="UploadButton_Click"
UploadConfigClick="UploaderControl_OnUploadConfigClick"
UploaderName="{Binding Source={x:Static tmsObjectsNames:TmsServiceNames.Workflow}}" />
<controls:UploaderControl ControlHeader="Archiver plugin"
ContentVisibility="{Binding ElementName=ThisUc, Path=ArchiverUploaderVisibility}"
HideButtonClick="OnHideButtonClick"
CurrentProvidedConfigPath="{Binding ElementName=ThisUc, Path=CurrentArchiverPluginConfigPath, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
PreviousConfigPathsCollection="{Binding ElementName=ThisUc, Path=PreviousArchiverPluginConfigPathsCollection}"
AutoUploadAfterBuild="{Binding ElementName=ThisUc,Path=ArchiverAutoUpload, Mode=TwoWay}"
CurrentProvidedPath="{Binding ElementName=ThisUc, Path=CurrentArchiverPluginPath, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
OpenServerFolder="UploaderControl_OnOpenServerFolder"
DockPanel.Dock="Top"
PreviousPathsCollection="{Binding ElementName=ThisUc, Path=PreviousArchiverPluginPathsCollection}"
LocalLastModified="{Binding ElementName=ThisUc, Path=LocalArchiverPluginLastModified}"
LocalLastModifiedBrush="{Binding ElementName=ThisUc, Path=LocalArchiverPluginLastModifiedBrush}"
ServerLastModified="{Binding ElementName=ThisUc, Path=ServerArchiverPluginLastModified}"
ServerLastModifiedBrush="{Binding ElementName=ThisUc, Path=ServerArchiverPluginLastModifiedBrush}"
LocalConfigLastModified="{Binding ElementName=ThisUc, Path=LocalArchiverPluginConfigLastModified}"
LocalConfigLastModifiedBrush="{Binding ElementName=ThisUc, Path=LocalArchiverConfigLastModifiedBrush}"
ServerConfigLastModified="{Binding ElementName=ThisUc, Path=ServerArchiverPluginConfigLastModified}"
ServerConfigLastModifiedBrush="{Binding ElementName=ThisUc, Path=ServerArchiverConfigLastModifiedBrush}"
UploadPluginClick="UploadButton_Click"
UploadConfigClick="UploaderControl_OnUploadConfigClick"
UploaderName="{Binding Source={x:Static tmsObjectsNames:TmsServiceNames.Archiver}}" />
For all the dependency properties above I have separate properties that are almost identical, except they are for different uploader type (workflow, archive, processing). Do I really need it like that? I suppose not, but I don't know how to handle this better.
#region Wokrlfow plugin ConfigPathBox //this one will be 'repeated' six times - 3x for different file types and 2x for dll and xml
private string _currentWorkflowPluginConfigPath = Settings.Default.CurrentWorkflowPluginConfigPath;
public string CurrentWorkflowPluginConfigPath
{
get
{
return _currentWorkflowPluginConfigPath;
}
set
{
_currentWorkflowPluginConfigPath = value;
Settings.Default.CurrentWorkflowPluginConfigPath = value;
RaisePropertyChanged(nameof(CurrentWorkflowPluginConfigPath));
InitializeWorkflowPluginUploader();
}
}
private bool _prevWorkflowConfigPathsEventSubscribed;
private ObservableCollection<string> _previousWorkflowPluginConfigPathsCollection = Settings.Default.PreviousWorkflowPluginConfigPathsCollection ?? new ObservableCollection<string>();
public ObservableCollection<string> PreviousWorkflowPluginConfigPathsCollection
{
get
{
if (!_prevWorkflowConfigPathsEventSubscribed)
{
_previousWorkflowPluginConfigPathsCollection.CollectionChanged += _previousWorkflowConfigPathsList_CollectionChanged;
_prevWorkflowConfigPathsEventSubscribed = true;
}
return _previousWorkflowPluginConfigPathsCollection;
}
set { }
}
void _previousWorkflowConfigPathsList_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
RaisePropertyChanged(nameof(PreviousWorkflowPluginConfigPathsCollection));
Settings.Default.PreviousWorkflowPluginConfigPathsCollection = PreviousWorkflowPluginConfigPathsCollection;
}
#endregion
#region Workflow // this is a section for last modified info along with brushes for coloring. Again, these will be 'repeated' six times.
private string _localWorkflowPluginLastModified;
public string LocalWorkflowPluginLastModified
{
get
{
return _localWorkflowPluginLastModified;
}
set
{
_localWorkflowPluginLastModified = value;
RaisePropertyChanged(nameof(LocalWorkflowPluginLastModified));
Brush local;
Brush server;
ColorizeLabels(LocalWorkflowPluginLastModified, out local, ServerWorkflowPluginLastModified, out server);
LocalWorkflowPluginLastModifiedBrush = local;
ServerWorkflowPluginLastModifiedBrush = server;
}
}
private string _serverWorkflowPluginLastModified;
public string ServerWorkflowPluginLastModified
{
get
{
return _serverWorkflowPluginLastModified;
}
set
{
_serverWorkflowPluginLastModified = value;
RaisePropertyChanged(nameof(ServerWorkflowPluginLastModified));
Brush local;
Brush server;
ColorizeLabels(LocalWorkflowPluginLastModified, out local, ServerWorkflowPluginLastModified, out server);
LocalWorkflowPluginLastModifiedBrush = local;
ServerWorkflowPluginLastModifiedBrush = server;
}
}
private Brush _localWorkflowPluginLastModifiedBrush;
public Brush LocalWorkflowPluginLastModifiedBrush
{
get
{
return _localWorkflowPluginLastModifiedBrush;
}
set
{
_localWorkflowPluginLastModifiedBrush = value;
RaisePropertyChanged(nameof(LocalWorkflowPluginLastModifiedBrush));
}
}
private Brush _serverWorkflowPluginLastModifiedBrush;
public Brush ServerWorkflowPluginLastModifiedBrush
{
get
{
return _serverWorkflowPluginLastModifiedBrush;
}
set
{
_serverWorkflowPluginLastModifiedBrush = value;
RaisePropertyChanged(nameof(ServerWorkflowPluginLastModifiedBrush));
}
}
#endregion
I think I am handling button click events pretty well with switches, so that all uploaders point to the same handler and then proper object is launched:
private async void UploaderControl_OnUploadConfigClick(object sender, RoutedEventArgs e)
{
FileUploadInfo = "Preparing upload...";
Application.Current.MainWindow.Cursor = Cursors.Wait;
string pluginName = (sender as Controls.UploaderControl).UploaderName;
switch (pluginName)
{
case TmsServiceNames.Workflow:
await WorkflowFileUploader?.UploadConfig(false);
break;
case TmsServiceNames.Archiver:
await ArchiverFileUploader?.UploadConfig(false);
break;
case TmsServiceNames.PptService:
await PptFileUploader?.UploadConfig(false);
break;
}
Application.Current.MainWindow.Cursor = Cursors.Arrow;
}
I have a big problem with initialization of each of the FileUploader classes. For each of the three types I had to create a separate method:
private void InitializeWorkflowPluginUploader()
{
if (CurrentWorkflowPluginPath.IsExistingFilePath() && ServicesManager.Services.ContainsKey(TmsServiceNames.Workflow))
{
IProgress<FileWatcherProgress> p = new Progress<FileWatcherProgress>(x =>
{
LocalWorkflowPluginLastModified = x.LocalFileVersion ?? LocalWorkflowPluginLastModified;
ServerWorkflowPluginLastModified = x.ServerFileVersion ?? ServerWorkflowPluginLastModified;
LocalWorkflowPluginConfigLastModified = x.LocalConfigFileVersion ?? LocalWorkflowPluginConfigLastModified;
ServerWorkflowPluginConfigLastModified = x.ServerConfigFileVersion ?? ServerWorkflowPluginConfigLastModified;
FileUploadInfo = x.OverallInfo ?? FileUploadInfo;
if (x.PopupText != null)
{
LaunchUploaderPopup(x.PopupTitle, x.PopupText);
}
});
WorkflowFileUploader = new RemoteFileUploader(CurrentWorkflowPluginPath, CurrentWorkflowPluginConfigPath, new TmsFolderPaths().Workflow, WorkflowAutoUpload, ShowPopupAfterAutoUpload, ServicesManager.Services[TmsServiceNames.Workflow], p);
}
}
I would like to create all these in a single method, where I could pass a bunch of properties as parameters - in this case for example file paths and properties for status labels (LocalWorkflowPluginLastModified) etc, which are different for each file type.
So, summing up, while this is finished and will not grow any further, I would like to do a better structure next time, reduce the number of properties if possible? What would I do if I had to add 5 more file types, and then add 2 more labels to each of them?
Thanks a lot for your feedback!
It has:
As a result, this user control has got 17 dependency properties and 4 events:
Full XAML on dotnetfiddle, click on the View tab
MainWindow.xaml
Now, in my MainWindow.xaml file, apart from crap like status bar and menu bar, I need to define three UploaderControls. And this is where it starts being pretty monstrous (especially if I were to have e.g. 10 types of files to upload) For each of the controls I need a separate set of properties to be bound.
Apart from that there's a bunch of miscellaneous props for visbility, auto-uplad and event handlers. I am not really concerned about those.
<controls:UploaderControl ControlHeader="Workflow plugin"
ContentVisibility="{Binding ElementName=ThisUc, Path=WorkflowUploaderVisibility}"
HideButtonClick="OnHideButtonClick"
CurrentProvidedPath="{Binding ElementName=ThisUc, Path=CurrentWorkflowPluginPath, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
PreviousPathsCollection="{Binding ElementName=ThisUc, Path=PreviousWorkflowPluginPathsCollection}"
CurrentProvidedConfigPath="{Binding ElementName=ThisUc, Path=CurrentWorkflowPluginConfigPath, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
PreviousConfigPathsCollection="{Binding ElementName=ThisUc, Path=PreviousWorkflowPluginConfigPathsCollection}"
DockPanel.Dock="Top"
OpenServerFolder="UploaderControl_OnOpenServerFolder"
AutoUploadAfterBuild="{Binding ElementName=ThisUc,Path=WorkflowAutoUpload,Mode=TwoWay}"
LocalLastModified="{Binding ElementName=ThisUc, Path=LocalWorkflowPluginLastModified}"
LocalLastModifiedBrush="{Binding ElementName=ThisUc, Path=LocalWorkflowPluginLastModifiedBrush}"
ServerLastModified="{Binding ElementName=ThisUc, Path=ServerWorkflowPluginLastModified}"
ServerLastModifiedBrush="{Binding ElementName=ThisUc, Path=ServerWorkflowPluginLastModifiedBrush}"
LocalConfigLastModified="{Binding ElementName=ThisUc, Path=LocalWorkflowPluginConfigLastModified}"
LocalConfigLastModifiedBrush="{Binding ElementName=ThisUc, Path=LocalWorkflowConfigLastModifiedBrush}"
ServerConfigLastModified="{Binding ElementName=ThisUc, Path=ServerWorkflowPluginConfigLastModified}"
ServerConfigLastModifiedBrush="{Binding ElementName=ThisUc, Path=ServerWorkflowConfigLastModifiedBrush}"
UploadPluginClick="UploadButton_Click"
UploadConfigClick="UploaderControl_OnUploadConfigClick"
UploaderName="{Binding Source={x:Static tmsObjectsNames:TmsServiceNames.Workflow}}" />
<controls:UploaderControl ControlHeader="Archiver plugin"
ContentVisibility="{Binding ElementName=ThisUc, Path=ArchiverUploaderVisibility}"
HideButtonClick="OnHideButtonClick"
CurrentProvidedConfigPath="{Binding ElementName=ThisUc, Path=CurrentArchiverPluginConfigPath, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
PreviousConfigPathsCollection="{Binding ElementName=ThisUc, Path=PreviousArchiverPluginConfigPathsCollection}"
AutoUploadAfterBuild="{Binding ElementName=ThisUc,Path=ArchiverAutoUpload, Mode=TwoWay}"
CurrentProvidedPath="{Binding ElementName=ThisUc, Path=CurrentArchiverPluginPath, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
OpenServerFolder="UploaderControl_OnOpenServerFolder"
DockPanel.Dock="Top"
PreviousPathsCollection="{Binding ElementName=ThisUc, Path=PreviousArchiverPluginPathsCollection}"
LocalLastModified="{Binding ElementName=ThisUc, Path=LocalArchiverPluginLastModified}"
LocalLastModifiedBrush="{Binding ElementName=ThisUc, Path=LocalArchiverPluginLastModifiedBrush}"
ServerLastModified="{Binding ElementName=ThisUc, Path=ServerArchiverPluginLastModified}"
ServerLastModifiedBrush="{Binding ElementName=ThisUc, Path=ServerArchiverPluginLastModifiedBrush}"
LocalConfigLastModified="{Binding ElementName=ThisUc, Path=LocalArchiverPluginConfigLastModified}"
LocalConfigLastModifiedBrush="{Binding ElementName=ThisUc, Path=LocalArchiverConfigLastModifiedBrush}"
ServerConfigLastModified="{Binding ElementName=ThisUc, Path=ServerArchiverPluginConfigLastModified}"
ServerConfigLastModifiedBrush="{Binding ElementName=ThisUc, Path=ServerArchiverConfigLastModifiedBrush}"
UploadPluginClick="UploadButton_Click"
UploadConfigClick="UploaderControl_OnUploadConfigClick"
UploaderName="{Binding Source={x:Static tmsObjectsNames:TmsServiceNames.Archiver}}" />
C#
For all the dependency properties above I have separate properties that are almost identical, except they are for different uploader type (workflow, archive, processing). Do I really need it like that? I suppose not, but I don't know how to handle this better.
Sample properties
#region Wokrlfow plugin ConfigPathBox //this one will be 'repeated' six times - 3x for different file types and 2x for dll and xml
private string _currentWorkflowPluginConfigPath = Settings.Default.CurrentWorkflowPluginConfigPath;
public string CurrentWorkflowPluginConfigPath
{
get
{
return _currentWorkflowPluginConfigPath;
}
set
{
_currentWorkflowPluginConfigPath = value;
Settings.Default.CurrentWorkflowPluginConfigPath = value;
RaisePropertyChanged(nameof(CurrentWorkflowPluginConfigPath));
InitializeWorkflowPluginUploader();
}
}
private bool _prevWorkflowConfigPathsEventSubscribed;
private ObservableCollection<string> _previousWorkflowPluginConfigPathsCollection = Settings.Default.PreviousWorkflowPluginConfigPathsCollection ?? new ObservableCollection<string>();
public ObservableCollection<string> PreviousWorkflowPluginConfigPathsCollection
{
get
{
if (!_prevWorkflowConfigPathsEventSubscribed)
{
_previousWorkflowPluginConfigPathsCollection.CollectionChanged += _previousWorkflowConfigPathsList_CollectionChanged;
_prevWorkflowConfigPathsEventSubscribed = true;
}
return _previousWorkflowPluginConfigPathsCollection;
}
set { }
}
void _previousWorkflowConfigPathsList_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
RaisePropertyChanged(nameof(PreviousWorkflowPluginConfigPathsCollection));
Settings.Default.PreviousWorkflowPluginConfigPathsCollection = PreviousWorkflowPluginConfigPathsCollection;
}
#endregion
#region Workflow // this is a section for last modified info along with brushes for coloring. Again, these will be 'repeated' six times.
private string _localWorkflowPluginLastModified;
public string LocalWorkflowPluginLastModified
{
get
{
return _localWorkflowPluginLastModified;
}
set
{
_localWorkflowPluginLastModified = value;
RaisePropertyChanged(nameof(LocalWorkflowPluginLastModified));
Brush local;
Brush server;
ColorizeLabels(LocalWorkflowPluginLastModified, out local, ServerWorkflowPluginLastModified, out server);
LocalWorkflowPluginLastModifiedBrush = local;
ServerWorkflowPluginLastModifiedBrush = server;
}
}
private string _serverWorkflowPluginLastModified;
public string ServerWorkflowPluginLastModified
{
get
{
return _serverWorkflowPluginLastModified;
}
set
{
_serverWorkflowPluginLastModified = value;
RaisePropertyChanged(nameof(ServerWorkflowPluginLastModified));
Brush local;
Brush server;
ColorizeLabels(LocalWorkflowPluginLastModified, out local, ServerWorkflowPluginLastModified, out server);
LocalWorkflowPluginLastModifiedBrush = local;
ServerWorkflowPluginLastModifiedBrush = server;
}
}
private Brush _localWorkflowPluginLastModifiedBrush;
public Brush LocalWorkflowPluginLastModifiedBrush
{
get
{
return _localWorkflowPluginLastModifiedBrush;
}
set
{
_localWorkflowPluginLastModifiedBrush = value;
RaisePropertyChanged(nameof(LocalWorkflowPluginLastModifiedBrush));
}
}
private Brush _serverWorkflowPluginLastModifiedBrush;
public Brush ServerWorkflowPluginLastModifiedBrush
{
get
{
return _serverWorkflowPluginLastModifiedBrush;
}
set
{
_serverWorkflowPluginLastModifiedBrush = value;
RaisePropertyChanged(nameof(ServerWorkflowPluginLastModifiedBrush));
}
}
#endregion
I think I am handling button click events pretty well with switches, so that all uploaders point to the same handler and then proper object is launched:
private async void UploaderControl_OnUploadConfigClick(object sender, RoutedEventArgs e)
{
FileUploadInfo = "Preparing upload...";
Application.Current.MainWindow.Cursor = Cursors.Wait;
string pluginName = (sender as Controls.UploaderControl).UploaderName;
switch (pluginName)
{
case TmsServiceNames.Workflow:
await WorkflowFileUploader?.UploadConfig(false);
break;
case TmsServiceNames.Archiver:
await ArchiverFileUploader?.UploadConfig(false);
break;
case TmsServiceNames.PptService:
await PptFileUploader?.UploadConfig(false);
break;
}
Application.Current.MainWindow.Cursor = Cursors.Arrow;
}
I have a big problem with initialization of each of the FileUploader
classes.
For each of the three types I had to create a separate method:
private void InitializeWorkflowPluginUploader()
{
if (CurrentWorkflowPluginPath.IsExistingFilePath() && ServicesManager.Services.ContainsKey(TmsServiceNames.Workflow))
{
IProgress<FileWatcherProgress> p = new Progress<FileWatcherProgress>(x =>
{
LocalWorkflowPluginLastModified = x.LocalFileVersion ?? LocalWorkflowPluginLastModified;
ServerWorkflowPluginLastModified = x.ServerFileVersion ?? ServerWorkflowPluginLastModified;
LocalWorkflowPluginConfigLastModified = x.LocalConfigFileVersion ?? LocalWorkflowPluginConfigLastModified;
ServerWorkflowPluginConfigLastModified = x.ServerConfigFileVersion ?? ServerWorkflowPluginConfigLastModified;
FileUploadInfo = x.OverallInfo ?? FileUploadInfo;
if (x.PopupText != null)
{
LaunchUploaderPopup(x.PopupTitle, x.PopupText);
}
});
WorkflowFileUploader = new RemoteFileUploader(CurrentWorkflowPluginPath, CurrentWorkflowPluginConfigPath, new TmsFolderPaths().Workflow, WorkflowAutoUpload, ShowPopupAfterAutoUpload, ServicesManager.Services[TmsServiceNames.Workflow], p);
}
}
I would like to create all these in a single method, where I could pass a bunch of properties as parameters - in this case for example file paths and properties for status labels (LocalWorkflowPluginLastModified
) etc, which are different for each file type.
So, summing up, while this is finished and will not grow any further, I would like to do a better structure next time, reduce the number of properties if possible. What would I do if I had to add 5 more file types, and then add 2 more labels to each of them?
To keep things simpler and more reusable, I have created a user control for uploader section, as this will repeat three times - it has got:
As a result, this user control has got 17 dependency properties and 4 events:
Full XAML on dotnetfiddle, click on the View tab
Now, in my MainWindow.xaml file, apart from crap like status bar and menu bar, I need to define three UploaderControls. And this is where it starts being pretty monstrous (especially if I were to have e.g. 10 types of files to upload) For each of the controls I need a separate set of properties to be bound.
Apart from that there's a bunch of miscellaneous props for visbility, auto-uplad and event handlers. I am not really concerned about those.
<controls:UploaderControl ControlHeader="Workflow plugin"
ContentVisibility="{Binding ElementName=ThisUc, Path=WorkflowUploaderVisibility}"
HideButtonClick="OnHideButtonClick"
CurrentProvidedPath="{Binding ElementName=ThisUc, Path=CurrentWorkflowPluginPath, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
PreviousPathsCollection="{Binding ElementName=ThisUc, Path=PreviousWorkflowPluginPathsCollection}"
CurrentProvidedConfigPath="{Binding ElementName=ThisUc, Path=CurrentWorkflowPluginConfigPath, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
PreviousConfigPathsCollection="{Binding ElementName=ThisUc, Path=PreviousWorkflowPluginConfigPathsCollection}"
DockPanel.Dock="Top"
OpenServerFolder="UploaderControl_OnOpenServerFolder"
AutoUploadAfterBuild="{Binding ElementName=ThisUc,Path=WorkflowAutoUpload,Mode=TwoWay}"
LocalLastModified="{Binding ElementName=ThisUc, Path=LocalWorkflowPluginLastModified}"
LocalLastModifiedBrush="{Binding ElementName=ThisUc, Path=LocalWorkflowPluginLastModifiedBrush}"
ServerLastModified="{Binding ElementName=ThisUc, Path=ServerWorkflowPluginLastModified}"
ServerLastModifiedBrush="{Binding ElementName=ThisUc, Path=ServerWorkflowPluginLastModifiedBrush}"
LocalConfigLastModified="{Binding ElementName=ThisUc, Path=LocalWorkflowPluginConfigLastModified}"
LocalConfigLastModifiedBrush="{Binding ElementName=ThisUc, Path=LocalWorkflowConfigLastModifiedBrush}"
ServerConfigLastModified="{Binding ElementName=ThisUc, Path=ServerWorkflowPluginConfigLastModified}"
ServerConfigLastModifiedBrush="{Binding ElementName=ThisUc, Path=ServerWorkflowConfigLastModifiedBrush}"
UploadPluginClick="UploadButton_Click"
UploadConfigClick="UploaderControl_OnUploadConfigClick"
UploaderName="{Binding Source={x:Static tmsObjectsNames:TmsServiceNames.Workflow}}" />
<controls:UploaderControl ControlHeader="Archiver plugin"
ContentVisibility="{Binding ElementName=ThisUc, Path=ArchiverUploaderVisibility}"
HideButtonClick="OnHideButtonClick"
CurrentProvidedConfigPath="{Binding ElementName=ThisUc, Path=CurrentArchiverPluginConfigPath, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
PreviousConfigPathsCollection="{Binding ElementName=ThisUc, Path=PreviousArchiverPluginConfigPathsCollection}"
AutoUploadAfterBuild="{Binding ElementName=ThisUc,Path=ArchiverAutoUpload, Mode=TwoWay}"
CurrentProvidedPath="{Binding ElementName=ThisUc, Path=CurrentArchiverPluginPath, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
OpenServerFolder="UploaderControl_OnOpenServerFolder"
DockPanel.Dock="Top"
PreviousPathsCollection="{Binding ElementName=ThisUc, Path=PreviousArchiverPluginPathsCollection}"
LocalLastModified="{Binding ElementName=ThisUc, Path=LocalArchiverPluginLastModified}"
LocalLastModifiedBrush="{Binding ElementName=ThisUc, Path=LocalArchiverPluginLastModifiedBrush}"
ServerLastModified="{Binding ElementName=ThisUc, Path=ServerArchiverPluginLastModified}"
ServerLastModifiedBrush="{Binding ElementName=ThisUc, Path=ServerArchiverPluginLastModifiedBrush}"
LocalConfigLastModified="{Binding ElementName=ThisUc, Path=LocalArchiverPluginConfigLastModified}"
LocalConfigLastModifiedBrush="{Binding ElementName=ThisUc, Path=LocalArchiverConfigLastModifiedBrush}"
ServerConfigLastModified="{Binding ElementName=ThisUc, Path=ServerArchiverPluginConfigLastModified}"
ServerConfigLastModifiedBrush="{Binding ElementName=ThisUc, Path=ServerArchiverConfigLastModifiedBrush}"
UploadPluginClick="UploadButton_Click"
UploadConfigClick="UploaderControl_OnUploadConfigClick"
UploaderName="{Binding Source={x:Static tmsObjectsNames:TmsServiceNames.Archiver}}" />
For all the dependency properties above I have separate properties that are almost identical, except they are for different uploader type (workflow, archive, processing). Do I really need it like that? I suppose not, but I don't know how to handle this better.
#region Wokrlfow plugin ConfigPathBox //this one will be 'repeated' six times - 3x for different file types and 2x for dll and xml
private string _currentWorkflowPluginConfigPath = Settings.Default.CurrentWorkflowPluginConfigPath;
public string CurrentWorkflowPluginConfigPath
{
get
{
return _currentWorkflowPluginConfigPath;
}
set
{
_currentWorkflowPluginConfigPath = value;
Settings.Default.CurrentWorkflowPluginConfigPath = value;
RaisePropertyChanged(nameof(CurrentWorkflowPluginConfigPath));
InitializeWorkflowPluginUploader();
}
}
private bool _prevWorkflowConfigPathsEventSubscribed;
private ObservableCollection<string> _previousWorkflowPluginConfigPathsCollection = Settings.Default.PreviousWorkflowPluginConfigPathsCollection ?? new ObservableCollection<string>();
public ObservableCollection<string> PreviousWorkflowPluginConfigPathsCollection
{
get
{
if (!_prevWorkflowConfigPathsEventSubscribed)
{
_previousWorkflowPluginConfigPathsCollection.CollectionChanged += _previousWorkflowConfigPathsList_CollectionChanged;
_prevWorkflowConfigPathsEventSubscribed = true;
}
return _previousWorkflowPluginConfigPathsCollection;
}
set { }
}
void _previousWorkflowConfigPathsList_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
RaisePropertyChanged(nameof(PreviousWorkflowPluginConfigPathsCollection));
Settings.Default.PreviousWorkflowPluginConfigPathsCollection = PreviousWorkflowPluginConfigPathsCollection;
}
#endregion
#region Workflow // this is a section for last modified info along with brushes for coloring. Again, these will be 'repeated' six times.
private string _localWorkflowPluginLastModified;
public string LocalWorkflowPluginLastModified
{
get
{
return _localWorkflowPluginLastModified;
}
set
{
_localWorkflowPluginLastModified = value;
RaisePropertyChanged(nameof(LocalWorkflowPluginLastModified));
Brush local;
Brush server;
ColorizeLabels(LocalWorkflowPluginLastModified, out local, ServerWorkflowPluginLastModified, out server);
LocalWorkflowPluginLastModifiedBrush = local;
ServerWorkflowPluginLastModifiedBrush = server;
}
}
private string _serverWorkflowPluginLastModified;
public string ServerWorkflowPluginLastModified
{
get
{
return _serverWorkflowPluginLastModified;
}
set
{
_serverWorkflowPluginLastModified = value;
RaisePropertyChanged(nameof(ServerWorkflowPluginLastModified));
Brush local;
Brush server;
ColorizeLabels(LocalWorkflowPluginLastModified, out local, ServerWorkflowPluginLastModified, out server);
LocalWorkflowPluginLastModifiedBrush = local;
ServerWorkflowPluginLastModifiedBrush = server;
}
}
private Brush _localWorkflowPluginLastModifiedBrush;
public Brush LocalWorkflowPluginLastModifiedBrush
{
get
{
return _localWorkflowPluginLastModifiedBrush;
}
set
{
_localWorkflowPluginLastModifiedBrush = value;
RaisePropertyChanged(nameof(LocalWorkflowPluginLastModifiedBrush));
}
}
private Brush _serverWorkflowPluginLastModifiedBrush;
public Brush ServerWorkflowPluginLastModifiedBrush
{
get
{
return _serverWorkflowPluginLastModifiedBrush;
}
set
{
_serverWorkflowPluginLastModifiedBrush = value;
RaisePropertyChanged(nameof(ServerWorkflowPluginLastModifiedBrush));
}
}
#endregion
I think I am handling button click events pretty well with switches, so that all uploaders point to the same handler and then proper object is launched:
private async void UploaderControl_OnUploadConfigClick(object sender, RoutedEventArgs e)
{
FileUploadInfo = "Preparing upload...";
Application.Current.MainWindow.Cursor = Cursors.Wait;
string pluginName = (sender as Controls.UploaderControl).UploaderName;
switch (pluginName)
{
case TmsServiceNames.Workflow:
await WorkflowFileUploader?.UploadConfig(false);
break;
case TmsServiceNames.Archiver:
await ArchiverFileUploader?.UploadConfig(false);
break;
case TmsServiceNames.PptService:
await PptFileUploader?.UploadConfig(false);
break;
}
Application.Current.MainWindow.Cursor = Cursors.Arrow;
}
I have a big problem with initialization of each of the FileUploader classes. For each of the three types I had to create a separate method:
private void InitializeWorkflowPluginUploader()
{
if (CurrentWorkflowPluginPath.IsExistingFilePath() && ServicesManager.Services.ContainsKey(TmsServiceNames.Workflow))
{
IProgress<FileWatcherProgress> p = new Progress<FileWatcherProgress>(x =>
{
LocalWorkflowPluginLastModified = x.LocalFileVersion ?? LocalWorkflowPluginLastModified;
ServerWorkflowPluginLastModified = x.ServerFileVersion ?? ServerWorkflowPluginLastModified;
LocalWorkflowPluginConfigLastModified = x.LocalConfigFileVersion ?? LocalWorkflowPluginConfigLastModified;
ServerWorkflowPluginConfigLastModified = x.ServerConfigFileVersion ?? ServerWorkflowPluginConfigLastModified;
FileUploadInfo = x.OverallInfo ?? FileUploadInfo;
if (x.PopupText != null)
{
LaunchUploaderPopup(x.PopupTitle, x.PopupText);
}
});
WorkflowFileUploader = new RemoteFileUploader(CurrentWorkflowPluginPath, CurrentWorkflowPluginConfigPath, new TmsFolderPaths().Workflow, WorkflowAutoUpload, ShowPopupAfterAutoUpload, ServicesManager.Services[TmsServiceNames.Workflow], p);
}
}
I would like to create all these in a single method, where I could pass a bunch of properties as parameters - in this case for example file paths and properties for status labels (LocalWorkflowPluginLastModified) etc, which are different for each file type.
So, summing up, while this is finished and will not grow any further, I would like to do a better structure next time, reduce the number of properties if possible? What would I do if I had to add 5 more file types, and then add 2 more labels to each of them?
Thanks a lot for your feedback!
###Purpose of the application**
##Structure
###User controls
To keep things simpler and more reusable, I have created a user control for uploader section, as this will repeat three times.
It has:
As a result, this user control has got 17 dependency properties and 4 events:
Full XAML on dotnetfiddle, click on the View tab
MainWindow.xaml
Now, in my MainWindow.xaml file, apart from crap like status bar and menu bar, I need to define three UploaderControls. And this is where it starts being pretty monstrous (especially if I were to have e.g. 10 types of files to upload) For each of the controls I need a separate set of properties to be bound.
Apart from that there's a bunch of miscellaneous props for visbility, auto-uplad and event handlers. I am not really concerned about those.
<controls:UploaderControl ControlHeader="Workflow plugin"
ContentVisibility="{Binding ElementName=ThisUc, Path=WorkflowUploaderVisibility}"
HideButtonClick="OnHideButtonClick"
CurrentProvidedPath="{Binding ElementName=ThisUc, Path=CurrentWorkflowPluginPath, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
PreviousPathsCollection="{Binding ElementName=ThisUc, Path=PreviousWorkflowPluginPathsCollection}"
CurrentProvidedConfigPath="{Binding ElementName=ThisUc, Path=CurrentWorkflowPluginConfigPath, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
PreviousConfigPathsCollection="{Binding ElementName=ThisUc, Path=PreviousWorkflowPluginConfigPathsCollection}"
DockPanel.Dock="Top"
OpenServerFolder="UploaderControl_OnOpenServerFolder"
AutoUploadAfterBuild="{Binding ElementName=ThisUc,Path=WorkflowAutoUpload,Mode=TwoWay}"
LocalLastModified="{Binding ElementName=ThisUc, Path=LocalWorkflowPluginLastModified}"
LocalLastModifiedBrush="{Binding ElementName=ThisUc, Path=LocalWorkflowPluginLastModifiedBrush}"
ServerLastModified="{Binding ElementName=ThisUc, Path=ServerWorkflowPluginLastModified}"
ServerLastModifiedBrush="{Binding ElementName=ThisUc, Path=ServerWorkflowPluginLastModifiedBrush}"
LocalConfigLastModified="{Binding ElementName=ThisUc, Path=LocalWorkflowPluginConfigLastModified}"
LocalConfigLastModifiedBrush="{Binding ElementName=ThisUc, Path=LocalWorkflowConfigLastModifiedBrush}"
ServerConfigLastModified="{Binding ElementName=ThisUc, Path=ServerWorkflowPluginConfigLastModified}"
ServerConfigLastModifiedBrush="{Binding ElementName=ThisUc, Path=ServerWorkflowConfigLastModifiedBrush}"
UploadPluginClick="UploadButton_Click"
UploadConfigClick="UploaderControl_OnUploadConfigClick"
UploaderName="{Binding Source={x:Static tmsObjectsNames:TmsServiceNames.Workflow}}" />
<controls:UploaderControl ControlHeader="Archiver plugin"
ContentVisibility="{Binding ElementName=ThisUc, Path=ArchiverUploaderVisibility}"
HideButtonClick="OnHideButtonClick"
CurrentProvidedConfigPath="{Binding ElementName=ThisUc, Path=CurrentArchiverPluginConfigPath, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
PreviousConfigPathsCollection="{Binding ElementName=ThisUc, Path=PreviousArchiverPluginConfigPathsCollection}"
AutoUploadAfterBuild="{Binding ElementName=ThisUc,Path=ArchiverAutoUpload, Mode=TwoWay}"
CurrentProvidedPath="{Binding ElementName=ThisUc, Path=CurrentArchiverPluginPath, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
OpenServerFolder="UploaderControl_OnOpenServerFolder"
DockPanel.Dock="Top"
PreviousPathsCollection="{Binding ElementName=ThisUc, Path=PreviousArchiverPluginPathsCollection}"
LocalLastModified="{Binding ElementName=ThisUc, Path=LocalArchiverPluginLastModified}"
LocalLastModifiedBrush="{Binding ElementName=ThisUc, Path=LocalArchiverPluginLastModifiedBrush}"
ServerLastModified="{Binding ElementName=ThisUc, Path=ServerArchiverPluginLastModified}"
ServerLastModifiedBrush="{Binding ElementName=ThisUc, Path=ServerArchiverPluginLastModifiedBrush}"
LocalConfigLastModified="{Binding ElementName=ThisUc, Path=LocalArchiverPluginConfigLastModified}"
LocalConfigLastModifiedBrush="{Binding ElementName=ThisUc, Path=LocalArchiverConfigLastModifiedBrush}"
ServerConfigLastModified="{Binding ElementName=ThisUc, Path=ServerArchiverPluginConfigLastModified}"
ServerConfigLastModifiedBrush="{Binding ElementName=ThisUc, Path=ServerArchiverConfigLastModifiedBrush}"
UploadPluginClick="UploadButton_Click"
UploadConfigClick="UploaderControl_OnUploadConfigClick"
UploaderName="{Binding Source={x:Static tmsObjectsNames:TmsServiceNames.Archiver}}" />
C#
For all the dependency properties above I have separate properties that are almost identical, except they are for different uploader type (workflow, archive, processing). Do I really need it like that? I suppose not, but I don't know how to handle this better.
Sample properties
#region Wokrlfow plugin ConfigPathBox //this one will be 'repeated' six times - 3x for different file types and 2x for dll and xml
private string _currentWorkflowPluginConfigPath = Settings.Default.CurrentWorkflowPluginConfigPath;
public string CurrentWorkflowPluginConfigPath
{
get
{
return _currentWorkflowPluginConfigPath;
}
set
{
_currentWorkflowPluginConfigPath = value;
Settings.Default.CurrentWorkflowPluginConfigPath = value;
RaisePropertyChanged(nameof(CurrentWorkflowPluginConfigPath));
InitializeWorkflowPluginUploader();
}
}
private bool _prevWorkflowConfigPathsEventSubscribed;
private ObservableCollection<string> _previousWorkflowPluginConfigPathsCollection = Settings.Default.PreviousWorkflowPluginConfigPathsCollection ?? new ObservableCollection<string>();
public ObservableCollection<string> PreviousWorkflowPluginConfigPathsCollection
{
get
{
if (!_prevWorkflowConfigPathsEventSubscribed)
{
_previousWorkflowPluginConfigPathsCollection.CollectionChanged += _previousWorkflowConfigPathsList_CollectionChanged;
_prevWorkflowConfigPathsEventSubscribed = true;
}
return _previousWorkflowPluginConfigPathsCollection;
}
set { }
}
void _previousWorkflowConfigPathsList_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
RaisePropertyChanged(nameof(PreviousWorkflowPluginConfigPathsCollection));
Settings.Default.PreviousWorkflowPluginConfigPathsCollection = PreviousWorkflowPluginConfigPathsCollection;
}
#endregion
#region Workflow // this is a section for last modified info along with brushes for coloring. Again, these will be 'repeated' six times.
private string _localWorkflowPluginLastModified;
public string LocalWorkflowPluginLastModified
{
get
{
return _localWorkflowPluginLastModified;
}
set
{
_localWorkflowPluginLastModified = value;
RaisePropertyChanged(nameof(LocalWorkflowPluginLastModified));
Brush local;
Brush server;
ColorizeLabels(LocalWorkflowPluginLastModified, out local, ServerWorkflowPluginLastModified, out server);
LocalWorkflowPluginLastModifiedBrush = local;
ServerWorkflowPluginLastModifiedBrush = server;
}
}
private string _serverWorkflowPluginLastModified;
public string ServerWorkflowPluginLastModified
{
get
{
return _serverWorkflowPluginLastModified;
}
set
{
_serverWorkflowPluginLastModified = value;
RaisePropertyChanged(nameof(ServerWorkflowPluginLastModified));
Brush local;
Brush server;
ColorizeLabels(LocalWorkflowPluginLastModified, out local, ServerWorkflowPluginLastModified, out server);
LocalWorkflowPluginLastModifiedBrush = local;
ServerWorkflowPluginLastModifiedBrush = server;
}
}
private Brush _localWorkflowPluginLastModifiedBrush;
public Brush LocalWorkflowPluginLastModifiedBrush
{
get
{
return _localWorkflowPluginLastModifiedBrush;
}
set
{
_localWorkflowPluginLastModifiedBrush = value;
RaisePropertyChanged(nameof(LocalWorkflowPluginLastModifiedBrush));
}
}
private Brush _serverWorkflowPluginLastModifiedBrush;
public Brush ServerWorkflowPluginLastModifiedBrush
{
get
{
return _serverWorkflowPluginLastModifiedBrush;
}
set
{
_serverWorkflowPluginLastModifiedBrush = value;
RaisePropertyChanged(nameof(ServerWorkflowPluginLastModifiedBrush));
}
}
#endregion
I think I am handling button click events pretty well with switches, so that all uploaders point to the same handler and then proper object is launched:
private async void UploaderControl_OnUploadConfigClick(object sender, RoutedEventArgs e)
{
FileUploadInfo = "Preparing upload...";
Application.Current.MainWindow.Cursor = Cursors.Wait;
string pluginName = (sender as Controls.UploaderControl).UploaderName;
switch (pluginName)
{
case TmsServiceNames.Workflow:
await WorkflowFileUploader?.UploadConfig(false);
break;
case TmsServiceNames.Archiver:
await ArchiverFileUploader?.UploadConfig(false);
break;
case TmsServiceNames.PptService:
await PptFileUploader?.UploadConfig(false);
break;
}
Application.Current.MainWindow.Cursor = Cursors.Arrow;
}
I have a big problem with initialization of each of the FileUploader
classes.
For each of the three types I had to create a separate method:
private void InitializeWorkflowPluginUploader()
{
if (CurrentWorkflowPluginPath.IsExistingFilePath() && ServicesManager.Services.ContainsKey(TmsServiceNames.Workflow))
{
IProgress<FileWatcherProgress> p = new Progress<FileWatcherProgress>(x =>
{
LocalWorkflowPluginLastModified = x.LocalFileVersion ?? LocalWorkflowPluginLastModified;
ServerWorkflowPluginLastModified = x.ServerFileVersion ?? ServerWorkflowPluginLastModified;
LocalWorkflowPluginConfigLastModified = x.LocalConfigFileVersion ?? LocalWorkflowPluginConfigLastModified;
ServerWorkflowPluginConfigLastModified = x.ServerConfigFileVersion ?? ServerWorkflowPluginConfigLastModified;
FileUploadInfo = x.OverallInfo ?? FileUploadInfo;
if (x.PopupText != null)
{
LaunchUploaderPopup(x.PopupTitle, x.PopupText);
}
});
WorkflowFileUploader = new RemoteFileUploader(CurrentWorkflowPluginPath, CurrentWorkflowPluginConfigPath, new TmsFolderPaths().Workflow, WorkflowAutoUpload, ShowPopupAfterAutoUpload, ServicesManager.Services[TmsServiceNames.Workflow], p);
}
}
I would like to create all these in a single method, where I could pass a bunch of properties as parameters - in this case for example file paths and properties for status labels (LocalWorkflowPluginLastModified
) etc, which are different for each file type.
So, summing up, while this is finished and will not grow any further, I would like to do a better structure next time, reduce the number of properties if possible. What would I do if I had to add 5 more file types, and then add 2 more labels to each of them?
As a result, this user control has got 17 dependency properties and 4 events:
Full XAML on dotnetfiddle, click on the View tab
Now, in my MainWindow.xaml file, apart from crap like status bar and menu bar, I need to define three UploaderControls. And this is where it starts being pretty monstrous (especially if I were to have e.g. 10 types of files to upload) For each of the controls I need a separate set of properties to be bound.
Apart from that there's a bunch of miscellaneous props for visbility, auto-uplad and event handlers. I am not really concerned about those.
<controls:UploaderControl ControlHeader="Workflow plugin"
ContentVisibility="{Binding ElementName=ThisUc, Path=WorkflowUploaderVisibility}"
HideButtonClick="OnHideButtonClick"
CurrentProvidedPath="{Binding ElementName=ThisUc, Path=CurrentWorkflowPluginPath, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
PreviousPathsCollection="{Binding ElementName=ThisUc, Path=PreviousWorkflowPluginPathsCollection}"
CurrentProvidedConfigPath="{Binding ElementName=ThisUc, Path=CurrentWorkflowPluginConfigPath, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
PreviousConfigPathsCollection="{Binding ElementName=ThisUc, Path=PreviousWorkflowPluginConfigPathsCollection}"
DockPanel.Dock="Top"
OpenServerFolder="UploaderControl_OnOpenServerFolder"
AutoUploadAfterBuild="{Binding ElementName=ThisUc,Path=WorkflowAutoUpload,Mode=TwoWay}"
LocalLastModified="{Binding ElementName=ThisUc, Path=LocalWorkflowPluginLastModified}"
LocalLastModifiedBrush="{Binding ElementName=ThisUc, Path=LocalWorkflowPluginLastModifiedBrush}"
ServerLastModified="{Binding ElementName=ThisUc, Path=ServerWorkflowPluginLastModified}"
ServerLastModifiedBrush="{Binding ElementName=ThisUc, Path=ServerWorkflowPluginLastModifiedBrush}"
LocalConfigLastModified="{Binding ElementName=ThisUc, Path=LocalWorkflowPluginConfigLastModified}"
LocalConfigLastModifiedBrush="{Binding ElementName=ThisUc, Path=LocalWorkflowConfigLastModifiedBrush}"
ServerConfigLastModified="{Binding ElementName=ThisUc, Path=ServerWorkflowPluginConfigLastModified}"
ServerConfigLastModifiedBrush="{Binding ElementName=ThisUc, Path=ServerWorkflowConfigLastModifiedBrush}"
UploadPluginClick="UploadButton_Click"
UploadConfigClick="UploaderControl_OnUploadConfigClick"
UploaderName="{Binding Source={x:Static tmsObjectsNames:TmsServiceNames.Workflow}}" />
<controls:UploaderControl ControlHeader="Archiver plugin"
ContentVisibility="{Binding ElementName=ThisUc, Path=ArchiverUploaderVisibility}"
HideButtonClick="OnHideButtonClick"
CurrentProvidedConfigPath="{Binding ElementName=ThisUc, Path=CurrentArchiverPluginConfigPath, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
PreviousConfigPathsCollection="{Binding ElementName=ThisUc, Path=PreviousArchiverPluginConfigPathsCollection}"
AutoUploadAfterBuild="{Binding ElementName=ThisUc,Path=ArchiverAutoUpload, Mode=TwoWay}"
CurrentProvidedPath="{Binding ElementName=ThisUc, Path=CurrentArchiverPluginPath, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
OpenServerFolder="UploaderControl_OnOpenServerFolder"
DockPanel.Dock="Top"
PreviousPathsCollection="{Binding ElementName=ThisUc, Path=PreviousArchiverPluginPathsCollection}"
LocalLastModified="{Binding ElementName=ThisUc, Path=LocalArchiverPluginLastModified}"
LocalLastModifiedBrush="{Binding ElementName=ThisUc, Path=LocalArchiverPluginLastModifiedBrush}"
ServerLastModified="{Binding ElementName=ThisUc, Path=ServerArchiverPluginLastModified}"
ServerLastModifiedBrush="{Binding ElementName=ThisUc, Path=ServerArchiverPluginLastModifiedBrush}"
LocalConfigLastModified="{Binding ElementName=ThisUc, Path=LocalArchiverPluginConfigLastModified}"
LocalConfigLastModifiedBrush="{Binding ElementName=ThisUc, Path=LocalArchiverConfigLastModifiedBrush}"
ServerConfigLastModified="{Binding ElementName=ThisUc, Path=ServerArchiverPluginConfigLastModified}"
ServerConfigLastModifiedBrush="{Binding ElementName=ThisUc, Path=ServerArchiverConfigLastModifiedBrush}"
UploadPluginClick="UploadButton_Click"
UploadConfigClick="UploaderControl_OnUploadConfigClick"
UploaderName="{Binding Source={x:Static tmsObjectsNames:TmsServiceNames.Archiver}}" />
For all the dependency properties above I have separate properties that are almost identical, except they are for different uploader type (workflow, archive, processing). Do I really need it like that? I suppose not, but I don't know how to handle this better.
#region Wokrlfow plugin ConfigPathBox //this one will be 'repeated' six times - 3x for different file types and 2x for dll and xml
private string _currentWorkflowPluginConfigPath = Settings.Default.CurrentWorkflowPluginConfigPath;
public string CurrentWorkflowPluginConfigPath
{
get
{
return _currentWorkflowPluginConfigPath;
}
set
{
_currentWorkflowPluginConfigPath = value;
Settings.Default.CurrentWorkflowPluginConfigPath = value;
RaisePropertyChanged(nameof(CurrentWorkflowPluginConfigPath));
InitializeWorkflowPluginUploader();
}
}
private bool _prevWorkflowConfigPathsEventSubscribed;
private ObservableCollection<string> _previousWorkflowPluginConfigPathsCollection = Settings.Default.PreviousWorkflowPluginConfigPathsCollection ?? new ObservableCollection<string>();
public ObservableCollection<string> PreviousWorkflowPluginConfigPathsCollection
{
get
{
if (!_prevWorkflowConfigPathsEventSubscribed)
{
_previousWorkflowPluginConfigPathsCollection.CollectionChanged += _previousWorkflowConfigPathsList_CollectionChanged;
_prevWorkflowConfigPathsEventSubscribed = true;
}
return _previousWorkflowPluginConfigPathsCollection;
}
set { }
}
void _previousWorkflowConfigPathsList_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
RaisePropertyChanged(nameof(PreviousWorkflowPluginConfigPathsCollection));
Settings.Default.PreviousWorkflowPluginConfigPathsCollection = PreviousWorkflowPluginConfigPathsCollection;
}
#endregion
#region Workflow // this is a section for last modified info along with brushes for coloring. Again, these will be 'repeated' six times.
private string _localWorkflowPluginLastModified;
public string LocalWorkflowPluginLastModified
{
get
{
return _localWorkflowPluginLastModified;
}
set
{
_localWorkflowPluginLastModified = value;
RaisePropertyChanged(nameof(LocalWorkflowPluginLastModified));
Brush local;
Brush server;
ColorizeLabels(LocalWorkflowPluginLastModified, out local, ServerWorkflowPluginLastModified, out server);
LocalWorkflowPluginLastModifiedBrush = local;
ServerWorkflowPluginLastModifiedBrush = server;
}
}
private string _serverWorkflowPluginLastModified;
public string ServerWorkflowPluginLastModified
{
get
{
return _serverWorkflowPluginLastModified;
}
set
{
_serverWorkflowPluginLastModified = value;
RaisePropertyChanged(nameof(ServerWorkflowPluginLastModified));
Brush local;
Brush server;
ColorizeLabels(LocalWorkflowPluginLastModified, out local, ServerWorkflowPluginLastModified, out server);
LocalWorkflowPluginLastModifiedBrush = local;
ServerWorkflowPluginLastModifiedBrush = server;
}
}
private Brush _localWorkflowPluginLastModifiedBrush;
public Brush LocalWorkflowPluginLastModifiedBrush
{
get
{
return _localWorkflowPluginLastModifiedBrush;
}
set
{
_localWorkflowPluginLastModifiedBrush = value;
RaisePropertyChanged(nameof(LocalWorkflowPluginLastModifiedBrush));
}
}
private Brush _serverWorkflowPluginLastModifiedBrush;
public Brush ServerWorkflowPluginLastModifiedBrush
{
get
{
return _serverWorkflowPluginLastModifiedBrush;
}
set
{
_serverWorkflowPluginLastModifiedBrush = value;
RaisePropertyChanged(nameof(ServerWorkflowPluginLastModifiedBrush));
}
}
#endregion
I think I am handling button click events pretty well with switches, so that all uploaders point to the same handler and then proper object is launched:
private async void UploaderControl_OnUploadConfigClick(object sender, RoutedEventArgs e)
{
FileUploadInfo = "Preparing upload...";
Application.Current.MainWindow.Cursor = Cursors.Wait;
string pluginName = (sender as Controls.UploaderControl).UploaderName;
switch (pluginName)
{
case TmsServiceNames.Workflow:
await WorkflowFileUploader?.UploadConfig(false);
break;
case TmsServiceNames.Archiver:
await ArchiverFileUploader?.UploadConfig(false);
break;
case TmsServiceNames.PptService:
await PptFileUploader?.UploadConfig(false);
break;
}
Application.Current.MainWindow.Cursor = Cursors.Arrow;
}
I have a big problem with initialization of each of the FileUploader classes. For each of the three types I had to create a separate method:
private void InitializeWorkflowPluginUploader()
{
if (CurrentWorkflowPluginPath.IsExistingFilePath() && ServicesManager.Services.ContainsKey(TmsServiceNames.Workflow))
{
IProgress<FileWatcherProgress> p = new Progress<FileWatcherProgress>(x =>
{
LocalWorkflowPluginLastModified = x.LocalFileVersion ?? LocalWorkflowPluginLastModified;
ServerWorkflowPluginLastModified = x.ServerFileVersion ?? ServerWorkflowPluginLastModified;
LocalWorkflowPluginConfigLastModified = x.LocalConfigFileVersion ?? LocalWorkflowPluginConfigLastModified;
ServerWorkflowPluginConfigLastModified = x.ServerConfigFileVersion ?? ServerWorkflowPluginConfigLastModified;
FileUploadInfo = x.OverallInfo ?? FileUploadInfo;
if (x.PopupText != null)
{
LaunchUploaderPopup(x.PopupTitle, x.PopupText);
}
});
WorkflowFileUploader = new RemoteFileUploader(CurrentWorkflowPluginPath, CurrentWorkflowPluginConfigPath, new TmsFolderPaths().Workflow, WorkflowAutoUpload, ShowPopupAfterAutoUpload, ServicesManager.Services[TmsServiceNames.Workflow], p);
}
}
I would like to create all these in a single method, where I could pass a bunch of properties as parameters - in this case for example file paths and properties for status labels (LocalWorkflowPluginLastModified) etc, which are different for each file type.
So, summing up, while this is finished and will not grow any further, I would like to do a better structure next time, reduce the number of properties if possible? What would I do if I had to add 5 more file types, and then add 2 more labels to each of them?
Thanks a lot for your feedback!
As a result, this user control has got 17 dependency properties and 4 events:
Full XAML on dotnetfiddle, click on the View tab
Now, in my MainWindow.xaml file, apart from crap like status bar and menu bar, I need to define three UploaderControls. And this is where it starts being pretty monstrous (especially if I were to have e.g. 10 types of files to upload) For each of the controls I need a separate set of properties to be bound.
Apart from that there's a bunch of miscellaneous props for visbility, auto-uplad and event handlers. I am not really concerned about those.
For all the dependency properties above I have separate properties that are almost identical, except they are for different uploader type (workflow, archive, processing). Do I really need it like that? I suppose not, but I don't know how to handle this better.
I think I am handling button click events pretty well with switches, so that all uploaders point to the same handler and then proper object is launched:
private async void UploaderControl_OnUploadConfigClick(object sender, RoutedEventArgs e)
{
FileUploadInfo = "Preparing upload...";
Application.Current.MainWindow.Cursor = Cursors.Wait;
string pluginName = (sender as Controls.UploaderControl).UploaderName;
switch (pluginName)
{
case TmsServiceNames.Workflow:
await WorkflowFileUploader?.UploadConfig(false);
break;
case TmsServiceNames.Archiver:
await ArchiverFileUploader?.UploadConfig(false);
break;
case TmsServiceNames.PptService:
await PptFileUploader?.UploadConfig(false);
break;
}
Application.Current.MainWindow.Cursor = Cursors.Arrow;
}
I have a big problem with initialization of each of the FileUploader classes. For each of the three types I had to create a separate method:
private void InitializeWorkflowPluginUploader()
{
if (CurrentWorkflowPluginPath.IsExistingFilePath() && ServicesManager.Services.ContainsKey(TmsServiceNames.Workflow))
{
IProgress<FileWatcherProgress> p = new Progress<FileWatcherProgress>(x =>
{
LocalWorkflowPluginLastModified = x.LocalFileVersion ?? LocalWorkflowPluginLastModified;
ServerWorkflowPluginLastModified = x.ServerFileVersion ?? ServerWorkflowPluginLastModified;
LocalWorkflowPluginConfigLastModified = x.LocalConfigFileVersion ?? LocalWorkflowPluginConfigLastModified;
ServerWorkflowPluginConfigLastModified = x.ServerConfigFileVersion ?? ServerWorkflowPluginConfigLastModified;
FileUploadInfo = x.OverallInfo ?? FileUploadInfo;
if (x.PopupText != null)
{
LaunchUploaderPopup(x.PopupTitle, x.PopupText);
}
});
WorkflowFileUploader = new RemoteFileUploader(CurrentWorkflowPluginPath, CurrentWorkflowPluginConfigPath, new TmsFolderPaths().Workflow, WorkflowAutoUpload, ShowPopupAfterAutoUpload, ServicesManager.Services[TmsServiceNames.Workflow], p);
}
}
I would like to create all these in a single method, where I could pass a bunch of properties as parameters - in this case for example file paths and properties for status labels (LocalWorkflowPluginLastModified) etc, which are different for each file type.
So, summing up, while this is finished and will not grow any further, I would like to do a better structure next time, reduce the number of properties if possible? What would I do if I had to add 5 more file types, and then add 2 more labels to each of them?
Thanks a lot for your feedback!
As a result, this user control has got 17 dependency properties and 4 events:
Full XAML on dotnetfiddle, click on the View tab
Now, in my MainWindow.xaml file, apart from crap like status bar and menu bar, I need to define three UploaderControls. And this is where it starts being pretty monstrous (especially if I were to have e.g. 10 types of files to upload) For each of the controls I need a separate set of properties to be bound.
Apart from that there's a bunch of miscellaneous props for visbility, auto-uplad and event handlers. I am not really concerned about those.
<controls:UploaderControl ControlHeader="Workflow plugin"
ContentVisibility="{Binding ElementName=ThisUc, Path=WorkflowUploaderVisibility}"
HideButtonClick="OnHideButtonClick"
CurrentProvidedPath="{Binding ElementName=ThisUc, Path=CurrentWorkflowPluginPath, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
PreviousPathsCollection="{Binding ElementName=ThisUc, Path=PreviousWorkflowPluginPathsCollection}"
CurrentProvidedConfigPath="{Binding ElementName=ThisUc, Path=CurrentWorkflowPluginConfigPath, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
PreviousConfigPathsCollection="{Binding ElementName=ThisUc, Path=PreviousWorkflowPluginConfigPathsCollection}"
DockPanel.Dock="Top"
OpenServerFolder="UploaderControl_OnOpenServerFolder"
AutoUploadAfterBuild="{Binding ElementName=ThisUc,Path=WorkflowAutoUpload,Mode=TwoWay}"
LocalLastModified="{Binding ElementName=ThisUc, Path=LocalWorkflowPluginLastModified}"
LocalLastModifiedBrush="{Binding ElementName=ThisUc, Path=LocalWorkflowPluginLastModifiedBrush}"
ServerLastModified="{Binding ElementName=ThisUc, Path=ServerWorkflowPluginLastModified}"
ServerLastModifiedBrush="{Binding ElementName=ThisUc, Path=ServerWorkflowPluginLastModifiedBrush}"
LocalConfigLastModified="{Binding ElementName=ThisUc, Path=LocalWorkflowPluginConfigLastModified}"
LocalConfigLastModifiedBrush="{Binding ElementName=ThisUc, Path=LocalWorkflowConfigLastModifiedBrush}"
ServerConfigLastModified="{Binding ElementName=ThisUc, Path=ServerWorkflowPluginConfigLastModified}"
ServerConfigLastModifiedBrush="{Binding ElementName=ThisUc, Path=ServerWorkflowConfigLastModifiedBrush}"
UploadPluginClick="UploadButton_Click"
UploadConfigClick="UploaderControl_OnUploadConfigClick"
UploaderName="{Binding Source={x:Static tmsObjectsNames:TmsServiceNames.Workflow}}" />
<controls:UploaderControl ControlHeader="Archiver plugin"
ContentVisibility="{Binding ElementName=ThisUc, Path=ArchiverUploaderVisibility}"
HideButtonClick="OnHideButtonClick"
CurrentProvidedConfigPath="{Binding ElementName=ThisUc, Path=CurrentArchiverPluginConfigPath, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
PreviousConfigPathsCollection="{Binding ElementName=ThisUc, Path=PreviousArchiverPluginConfigPathsCollection}"
AutoUploadAfterBuild="{Binding ElementName=ThisUc,Path=ArchiverAutoUpload, Mode=TwoWay}"
CurrentProvidedPath="{Binding ElementName=ThisUc, Path=CurrentArchiverPluginPath, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
OpenServerFolder="UploaderControl_OnOpenServerFolder"
DockPanel.Dock="Top"
PreviousPathsCollection="{Binding ElementName=ThisUc, Path=PreviousArchiverPluginPathsCollection}"
LocalLastModified="{Binding ElementName=ThisUc, Path=LocalArchiverPluginLastModified}"
LocalLastModifiedBrush="{Binding ElementName=ThisUc, Path=LocalArchiverPluginLastModifiedBrush}"
ServerLastModified="{Binding ElementName=ThisUc, Path=ServerArchiverPluginLastModified}"
ServerLastModifiedBrush="{Binding ElementName=ThisUc, Path=ServerArchiverPluginLastModifiedBrush}"
LocalConfigLastModified="{Binding ElementName=ThisUc, Path=LocalArchiverPluginConfigLastModified}"
LocalConfigLastModifiedBrush="{Binding ElementName=ThisUc, Path=LocalArchiverConfigLastModifiedBrush}"
ServerConfigLastModified="{Binding ElementName=ThisUc, Path=ServerArchiverPluginConfigLastModified}"
ServerConfigLastModifiedBrush="{Binding ElementName=ThisUc, Path=ServerArchiverConfigLastModifiedBrush}"
UploadPluginClick="UploadButton_Click"
UploadConfigClick="UploaderControl_OnUploadConfigClick"
UploaderName="{Binding Source={x:Static tmsObjectsNames:TmsServiceNames.Archiver}}" />
For all the dependency properties above I have separate properties that are almost identical, except they are for different uploader type (workflow, archive, processing). Do I really need it like that? I suppose not, but I don't know how to handle this better.
#region Wokrlfow plugin ConfigPathBox //this one will be 'repeated' six times - 3x for different file types and 2x for dll and xml
private string _currentWorkflowPluginConfigPath = Settings.Default.CurrentWorkflowPluginConfigPath;
public string CurrentWorkflowPluginConfigPath
{
get
{
return _currentWorkflowPluginConfigPath;
}
set
{
_currentWorkflowPluginConfigPath = value;
Settings.Default.CurrentWorkflowPluginConfigPath = value;
RaisePropertyChanged(nameof(CurrentWorkflowPluginConfigPath));
InitializeWorkflowPluginUploader();
}
}
private bool _prevWorkflowConfigPathsEventSubscribed;
private ObservableCollection<string> _previousWorkflowPluginConfigPathsCollection = Settings.Default.PreviousWorkflowPluginConfigPathsCollection ?? new ObservableCollection<string>();
public ObservableCollection<string> PreviousWorkflowPluginConfigPathsCollection
{
get
{
if (!_prevWorkflowConfigPathsEventSubscribed)
{
_previousWorkflowPluginConfigPathsCollection.CollectionChanged += _previousWorkflowConfigPathsList_CollectionChanged;
_prevWorkflowConfigPathsEventSubscribed = true;
}
return _previousWorkflowPluginConfigPathsCollection;
}
set { }
}
void _previousWorkflowConfigPathsList_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
RaisePropertyChanged(nameof(PreviousWorkflowPluginConfigPathsCollection));
Settings.Default.PreviousWorkflowPluginConfigPathsCollection = PreviousWorkflowPluginConfigPathsCollection;
}
#endregion
#region Workflow // this is a section for last modified info along with brushes for coloring. Again, these will be 'repeated' six times.
private string _localWorkflowPluginLastModified;
public string LocalWorkflowPluginLastModified
{
get
{
return _localWorkflowPluginLastModified;
}
set
{
_localWorkflowPluginLastModified = value;
RaisePropertyChanged(nameof(LocalWorkflowPluginLastModified));
Brush local;
Brush server;
ColorizeLabels(LocalWorkflowPluginLastModified, out local, ServerWorkflowPluginLastModified, out server);
LocalWorkflowPluginLastModifiedBrush = local;
ServerWorkflowPluginLastModifiedBrush = server;
}
}
private string _serverWorkflowPluginLastModified;
public string ServerWorkflowPluginLastModified
{
get
{
return _serverWorkflowPluginLastModified;
}
set
{
_serverWorkflowPluginLastModified = value;
RaisePropertyChanged(nameof(ServerWorkflowPluginLastModified));
Brush local;
Brush server;
ColorizeLabels(LocalWorkflowPluginLastModified, out local, ServerWorkflowPluginLastModified, out server);
LocalWorkflowPluginLastModifiedBrush = local;
ServerWorkflowPluginLastModifiedBrush = server;
}
}
private Brush _localWorkflowPluginLastModifiedBrush;
public Brush LocalWorkflowPluginLastModifiedBrush
{
get
{
return _localWorkflowPluginLastModifiedBrush;
}
set
{
_localWorkflowPluginLastModifiedBrush = value;
RaisePropertyChanged(nameof(LocalWorkflowPluginLastModifiedBrush));
}
}
private Brush _serverWorkflowPluginLastModifiedBrush;
public Brush ServerWorkflowPluginLastModifiedBrush
{
get
{
return _serverWorkflowPluginLastModifiedBrush;
}
set
{
_serverWorkflowPluginLastModifiedBrush = value;
RaisePropertyChanged(nameof(ServerWorkflowPluginLastModifiedBrush));
}
}
#endregion
I think I am handling button click events pretty well with switches, so that all uploaders point to the same handler and then proper object is launched:
private async void UploaderControl_OnUploadConfigClick(object sender, RoutedEventArgs e)
{
FileUploadInfo = "Preparing upload...";
Application.Current.MainWindow.Cursor = Cursors.Wait;
string pluginName = (sender as Controls.UploaderControl).UploaderName;
switch (pluginName)
{
case TmsServiceNames.Workflow:
await WorkflowFileUploader?.UploadConfig(false);
break;
case TmsServiceNames.Archiver:
await ArchiverFileUploader?.UploadConfig(false);
break;
case TmsServiceNames.PptService:
await PptFileUploader?.UploadConfig(false);
break;
}
Application.Current.MainWindow.Cursor = Cursors.Arrow;
}
I have a big problem with initialization of each of the FileUploader classes. For each of the three types I had to create a separate method:
private void InitializeWorkflowPluginUploader()
{
if (CurrentWorkflowPluginPath.IsExistingFilePath() && ServicesManager.Services.ContainsKey(TmsServiceNames.Workflow))
{
IProgress<FileWatcherProgress> p = new Progress<FileWatcherProgress>(x =>
{
LocalWorkflowPluginLastModified = x.LocalFileVersion ?? LocalWorkflowPluginLastModified;
ServerWorkflowPluginLastModified = x.ServerFileVersion ?? ServerWorkflowPluginLastModified;
LocalWorkflowPluginConfigLastModified = x.LocalConfigFileVersion ?? LocalWorkflowPluginConfigLastModified;
ServerWorkflowPluginConfigLastModified = x.ServerConfigFileVersion ?? ServerWorkflowPluginConfigLastModified;
FileUploadInfo = x.OverallInfo ?? FileUploadInfo;
if (x.PopupText != null)
{
LaunchUploaderPopup(x.PopupTitle, x.PopupText);
}
});
WorkflowFileUploader = new RemoteFileUploader(CurrentWorkflowPluginPath, CurrentWorkflowPluginConfigPath, new TmsFolderPaths().Workflow, WorkflowAutoUpload, ShowPopupAfterAutoUpload, ServicesManager.Services[TmsServiceNames.Workflow], p);
}
}
I would like to create all these in a single method, where I could pass a bunch of properties as parameters - in this case for example file paths and properties for status labels (LocalWorkflowPluginLastModified) etc, which are different for each file type.
So, summing up, while this is finished and will not grow any further, I would like to do a better structure next time, reduce the number of properties if possible? What would I do if I had to add 5 more file types, and then add 2 more labels to each of them?
Thanks a lot for your feedback!