From 78ba78c22bb044714ebd0868e7b6b5bf1f22b000 Mon Sep 17 00:00:00 2001 From: Markus Quaritsch <markus.quaritsch@tugraz.at> Date: Fri, 15 Sep 2017 10:33:31 +0200 Subject: [PATCH] fix: updating canonicalization method works; corrected comparison of job hash for report integrity checks --- HashingTool/Helper/HashingHelper.cs | 10 +- .../ViewModel/HashComponentDataViewModel.cs | 23 +- HashingTool/ViewModel/HashedXMLFile.cs | 81 +++++-- .../VerifyComponentInputDataViewModel.cs | 12 +- .../ViewModel/VerifyResultDataViewModel.cs | 50 ++-- .../Views/VerifyComponentInputData.xaml | 2 +- HashingTool/Views/VerifyResults.xaml | 216 +++++++++++++----- 7 files changed, 272 insertions(+), 122 deletions(-) diff --git a/HashingTool/Helper/HashingHelper.cs b/HashingTool/Helper/HashingHelper.cs index cac69844fc..c3bebafe4d 100644 --- a/HashingTool/Helper/HashingHelper.cs +++ b/HashingTool/Helper/HashingHelper.cs @@ -91,10 +91,7 @@ namespace HashingTool.Helper var h = VectoHash.Load(xml); xmlViewModel.DigestValueComputed = h.ComputeHash(); xmlViewModel.DigestMethod = h.GetDigestMethod(); - var c14N = h.GetCanonicalizationMethods().ToArray(); - foreach (var c in c14N) { - xmlViewModel.CanonicalizationMethods.Add(c); - } + xmlViewModel.SetCanonicalizationMethod(h.GetCanonicalizationMethods()); } catch (Exception e) { xmlViewModel.XMLFile.XMLValidationErrors.Add(e.Message); xmlViewModel.DigestValueComputed = ""; @@ -110,10 +107,7 @@ namespace HashingTool.Helper try { var h = VectoHash.Load(xml); report.DigestMethod = h.GetDigestMethod(); - var c14N = h.GetCanonicalizationMethods().ToArray(); - foreach (var c in c14N) { - report.CanonicalizationMethods.Add(c); - } + report.SetCanonicalizationMethod(h.GetCanonicalizationMethods()); try { report.DigestValueRead = h.ReadHash(); } catch { diff --git a/HashingTool/ViewModel/HashComponentDataViewModel.cs b/HashingTool/ViewModel/HashComponentDataViewModel.cs index e5287341b8..7d9df0b825 100644 --- a/HashingTool/ViewModel/HashComponentDataViewModel.cs +++ b/HashingTool/ViewModel/HashComponentDataViewModel.cs @@ -62,8 +62,9 @@ namespace HashingTool.ViewModel private void SourceChanged(object sender, PropertyChangedEventArgs e) { - if (e.PropertyName == "Document" || e.PropertyName == "IsValid") - DoComputeHash(); + if (e.PropertyName == "Document" || e.PropertyName == "IsValid") { + DoComputeHash(); + } } private void SaveDocument() @@ -104,7 +105,7 @@ namespace HashingTool.ViewModel ComponentDataValid = false; DigestValue = ""; DigestMethod = ""; - CanonicalizationMethods.Clear(); + SetCanonicalizationMethod(new string[] { }); return; } @@ -113,7 +114,7 @@ namespace HashingTool.ViewModel ComponentDataValid = false; DigestValue = ""; _xmlFile.XMLValidationErrors.Clear(); - CanonicalizationMethods.Clear(); + SetCanonicalizationMethod(new string[] { }); var h = VectoHash.Load(_xmlFile.Document); @@ -152,21 +153,17 @@ namespace HashingTool.ViewModel ms.Flush(); ms.Seek(0, SeekOrigin.Begin); var h2 = VectoHash.Load(ms); - var c14N = h2.GetCanonicalizationMethods().ToArray(); - var digestMethod = h2.GetDigestMethod(); - DigestValue = h.ReadHash(); - foreach (var c in c14N) { - CanonicalizationMethods.Add(c); - } - RaisePropertyChanged("CanonicalizationMethods"); - DigestMethod = digestMethod; + DigestMethod = h2.GetDigestMethod(); + DigestValue = h2.ReadHash(); + SetCanonicalizationMethod(h2.GetCanonicalizationMethods()); } } } catch (Exception e) { ComponentDataValid = false; DigestValue = ""; _xmlFile.XMLValidationErrors.Add(e.Message); - CanonicalizationMethods.Clear(); + SetCanonicalizationMethod(new string[] { }); + DigestMethod = ""; } finally { _busy = false; _saveCommand.RaiseCanExecuteChanged(); diff --git a/HashingTool/ViewModel/HashedXMLFile.cs b/HashingTool/ViewModel/HashedXMLFile.cs index eb0db4f57a..cd02b40d9d 100644 --- a/HashingTool/ViewModel/HashedXMLFile.cs +++ b/HashingTool/ViewModel/HashedXMLFile.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Linq; @@ -78,6 +79,15 @@ namespace HashingTool.ViewModel public ObservableCollection<string> CanonicalizationMethods { get; private set; } + public void SetCanonicalizationMethod(IEnumerable<string> c14NMethods) + { + CanonicalizationMethods.Clear(); + foreach (var c14N in c14NMethods) { + CanonicalizationMethods.Add(c14N); + } + RaisePropertyChanged("CanonicalizationMethods"); + } + public string DigestMethod { get { return _digestMethod; } @@ -163,9 +173,11 @@ namespace HashingTool.ViewModel public class ReportXMLFile : HashedXMLFile { - private string _jobDigestValueRead; - private string _jobDigestMethod; - private string[] _jobCanonicalizationMethod; + private string _jobDigestValueReadRead; + private string _jobDigestMethodRead; + private string[] _jobCanonicalizationMethodRead; + private string _jobDigestComputed; + private bool _jobDigestValid; public ReportXMLFile(string name, Func<XmlDocument, Collection<string>, bool?> contentCheck, Action<XmlDocument, VectoXMLFile> hashValidation = null) @@ -202,44 +214,69 @@ namespace HashingTool.ViewModel jobc14NMethod = (from XmlNode node in c14NtMethodNodes select node.InnerText).ToArray(); } } - JobCanonicalizationMethod = jobc14NMethod; - JobDigestMethod = jobDigestMethod; - JobDigestValue = jobDigest; + JobCanonicalizationMethodRead = jobc14NMethod; + JobDigestMethodRead = jobDigestMethod; + JobDigestValueRead = jobDigest; } - public string JobDigestMethod + public string JobDigestMethodRead { - get { return _jobDigestMethod; } + get { return _jobDigestMethodRead; } set { - if (_jobDigestMethod == value) { + if (_jobDigestMethodRead == value) { return; } - _jobDigestMethod = value; - RaisePropertyChanged("JobDigestMethod"); + _jobDigestMethodRead = value; + RaisePropertyChanged("JobDigestMethodRead"); } } - public string[] JobCanonicalizationMethod + public string[] JobCanonicalizationMethodRead { - get { return _jobCanonicalizationMethod; } + get { return _jobCanonicalizationMethodRead; } set { - if (_jobCanonicalizationMethod == value) { + if (_jobCanonicalizationMethodRead == value) { return; } - _jobCanonicalizationMethod = value; - RaisePropertyChanged("JobCanonicalizationMethod"); + _jobCanonicalizationMethodRead = value; + RaisePropertyChanged("JobCanonicalizationMethodRead"); } } - public string JobDigestValue + public string JobDigestValueRead { - get { return _jobDigestValueRead; } + get { return _jobDigestValueReadRead; } internal set { - if (_jobDigestValueRead == value) { + if (_jobDigestValueReadRead == value) { + return; + } + _jobDigestValueReadRead = value; + RaisePropertyChanged("JobDigestValueRead"); + } + } + + public string JobDigestValueComputed + { + get { return _jobDigestComputed; } + set { + if (_jobDigestComputed == value) { + return; + } + _jobDigestComputed = value; + RaisePropertyChanged("JobDigestValueComputed"); + JobDigestValid = JobDigestValueComputed == JobDigestValueRead; + } + } + + public bool JobDigestValid + { + get { return _jobDigestValid; } + set { + if (_jobDigestValid == value) { return; } - _jobDigestValueRead = value; - RaisePropertyChanged("JobDigestValue"); + _jobDigestValid = value; + RaisePropertyChanged("JobDigestValid"); } } } @@ -296,7 +333,7 @@ namespace HashingTool.ViewModel Components.Clear(); DigestValueComputed = ""; DigestMethod = ""; - CanonicalizationMethods.Clear(); + SetCanonicalizationMethod(new string[] { }); JobDataValid = false; return; } diff --git a/HashingTool/ViewModel/VerifyComponentInputDataViewModel.cs b/HashingTool/ViewModel/VerifyComponentInputDataViewModel.cs index 8ee365ba66..a2479bbc86 100644 --- a/HashingTool/ViewModel/VerifyComponentInputDataViewModel.cs +++ b/HashingTool/ViewModel/VerifyComponentInputDataViewModel.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.ComponentModel; using System.IO; using System.Linq; @@ -9,7 +10,7 @@ using TUGraz.VectoHashing; namespace HashingTool.ViewModel { - public class VerifyComponentInputDataViewModel : HashedXMLFile, IMainView + public class VerifyComponentInputDataViewModel : HashedXMLFile, IMainView, INotifyPropertyChanged { private bool _componentDataValid; @@ -66,19 +67,18 @@ namespace HashingTool.ViewModel DigestValueComputed = h.ComputeHash(); ComponentDataValid = h.ValidateHash(); DigestMethod = h.GetDigestMethod(); - CanonicalizationMethods.Clear(); - foreach (var c in h.GetCanonicalizationMethods().ToArray()) { - CanonicalizationMethods.Add(c); - } + SetCanonicalizationMethod(h.GetCanonicalizationMethods()); + } catch (Exception e) { ComponentDataValid = false; DigestValueComputed = ""; DigestValueRead = ""; Component = ""; - CanonicalizationMethods.Clear(); + SetCanonicalizationMethod(new string[] { }); DigestMethod = ""; _xmlFile.XMLValidationErrors.Add(e.Message); } } + } } diff --git a/HashingTool/ViewModel/VerifyResultDataViewModel.cs b/HashingTool/ViewModel/VerifyResultDataViewModel.cs index cea7da0bdd..52baf9e984 100644 --- a/HashingTool/ViewModel/VerifyResultDataViewModel.cs +++ b/HashingTool/ViewModel/VerifyResultDataViewModel.cs @@ -31,8 +31,10 @@ namespace HashingTool.ViewModel private void Update(object sender, PropertyChangedEventArgs e) { - RaisePropertyChanged("ManufacturerReportValid"); - RaisePropertyChanged("CustomerReportReportValid"); + //RaisePropertyChanged("ManufacturerReportValid"); + //RaisePropertyChanged("CustomerReportReportValid"); + UpdateReportJobDigest(_manufacturerReport); + UpdateReportJobDigest(_customerReport); } @@ -64,21 +66,43 @@ namespace HashingTool.ViewModel public ObservableCollection<VectoXMLFile> Files { get; private set; } - public bool ManufacturerReportValid + //public bool ManufacturerReportValid + //{ + // get { + private void UpdateReportJobDigest(ReportXMLFile reportXML) { - get { - return _manufacturerReport.Valid != null && _manufacturerReport.Valid.Value && - _manufacturerReport.JobDigestValue == _jobFile.DigestValueComputed; + if (reportXML.Valid == null || !reportXML.Valid.Value) { + reportXML.JobDigestValueComputed = ""; + return; } - } - - public bool CustomerReportReportValid - { - get { - return _customerReport.Valid != null && _customerReport.Valid.Value && - _customerReport.JobDigestValue == _jobFile.DigestValueComputed; + try { + var h = VectoHash.Load(_jobFile.XMLFile.Document); + var jobDigest = h.ComputeHash(reportXML.JobCanonicalizationMethodRead, + reportXML.JobDigestMethodRead); + reportXML.JobDigestValueComputed = jobDigest; + } catch (Exception e) { + reportXML.JobDigestValueComputed = ""; } } + // } + //} + + //public bool CustomerReportReportValid + //{ + // get { + // if (_customerReport.Valid == null || !_customerReport.Valid.Value) { + // return false; + // } + // try { + // var h = VectoHash.Load(_jobFile.XMLFile.Document); + // var jobDigest = h.ComputeHash(_customerReport.JobCanonicalizationMethodRead, _customerReport.JobDigestMethodRead); + // _customerReport.JobDigestValueComputed = jobDigest; + // return _customerReport.JobDigestValueRead == jobDigest; + // } catch (Exception e) { + // return false; + // } + // } + //} } } diff --git a/HashingTool/Views/VerifyComponentInputData.xaml b/HashingTool/Views/VerifyComponentInputData.xaml index 642cef1f27..38531641c7 100644 --- a/HashingTool/Views/VerifyComponentInputData.xaml +++ b/HashingTool/Views/VerifyComponentInputData.xaml @@ -50,7 +50,7 @@ <Label Grid.Row="1" Grid.Column="0" Content="Canonicalization methods:" /> <TextBox Grid.Row="1" Grid.Column="1" - Text="{Binding CanonicalizationMethods ,Mode=OneWay, Converter={StaticResource CollectionConverter}}" + Text="{Binding CanonicalizationMethods, Mode=OneWay, Converter={StaticResource CollectionConverter}}" Margin="10,2" IsReadOnly="True" /> <Label Grid.Row="2" Grid.Column="0" Content="Digest method:" /> diff --git a/HashingTool/Views/VerifyResults.xaml b/HashingTool/Views/VerifyResults.xaml index c21c99e5e5..b42b13e957 100644 --- a/HashingTool/Views/VerifyResults.xaml +++ b/HashingTool/Views/VerifyResults.xaml @@ -72,16 +72,16 @@ </DataTemplate> <DataTemplate x:Key="ExpanderContentJobFile" DataType="viewModel:VectoXMLFile"> - <Grid> + <Grid Grid.IsSharedSizeScope="True"> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition /> <RowDefinition /> <RowDefinition /> - <RowDefinition/> + <RowDefinition /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> - <ColumnDefinition Width="Auto" /> + <ColumnDefinition Width="Auto" SharedSizeGroup="LabelsShareGroup" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <StackPanel Orientation="Horizontal" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2"> @@ -132,20 +132,13 @@ </DataTemplate> <DataTemplate x:Key="ExpanderContentReport" DataType="viewModel:ReportXMLFile"> - <Grid> + <Grid Grid.IsSharedSizeScope="True"> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition /> <RowDefinition /> - <RowDefinition /> - <RowDefinition /> - <RowDefinition/> - <RowDefinition/> </Grid.RowDefinitions> - <Grid.ColumnDefinitions> - <ColumnDefinition Width="Auto" /> - <ColumnDefinition Width="*" /> - </Grid.ColumnDefinitions> + <StackPanel Orientation="Horizontal" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2"> <Label> <Label.Content> @@ -176,59 +169,164 @@ </Button> </StackPanel> - <Label Grid.Row="1" Grid.Column="0" Content="Job CanonicalizationMethod:" /> - <TextBox Grid.Row="1" Grid.Column="1" Text="{Binding JobCanonicalizationMethod, Mode=OneWay, Converter={StaticResource CollectionConverter}}" - Margin="10,2" IsReadOnly="True" /> + <GroupBox Grid.Row="1" Header="Report Integrity" Margin="0,0,0,5" Style="{DynamicResource CustomGroupboxStyle}"> + <Grid> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="Auto" SharedSizeGroup="LabelsShareGroup" /> + <ColumnDefinition Width="*" /> + </Grid.ColumnDefinitions> + <Grid.RowDefinitions> + <RowDefinition /> + <RowDefinition /> + <RowDefinition /> + <RowDefinition /> + </Grid.RowDefinitions> - <Label Grid.Row="2" Grid.Column="0" Content="Job Digest Method:" /> - <TextBox Grid.Row="2" Grid.Column="1" Text="{Binding JobDigestMethod, Mode=OneWay}" - Margin="10,2" IsReadOnly="True" /> - - <Label Grid.Row="3" Grid.Column="0" Content="Job Digest Value:" - Style="{StaticResource DigestValueLabelStyle}" /> - <TextBox Grid.Row="3" Grid.Column="1" Text="{Binding JobDigestValue, Mode=OneWay}" - Margin="10,2" IsReadOnly="True" Style="{StaticResource DigestValueTextboxStyle}" /> + <Label Grid.Row="0" Grid.Column="0" Content="Canonicalization methods:" /> + <TextBox Grid.Row="0" Grid.Column="1" + Text="{Binding CanonicalizationMethods, Mode=OneWay , Converter={StaticResource CollectionConverter}}" + Margin="10,2" IsReadOnly="True" /> - <Label Grid.Row="4" Grid.Column="0" Content="Canonicalization methods:" /> - <TextBox Grid.Row="4" Grid.Column="1" - Text="{Binding CanonicalizationMethods, Mode=OneWay , Converter={StaticResource CollectionConverter}}" - Margin="10,2" IsReadOnly="True" /> + <Label Grid.Row="1" Grid.Column="0" Content="Digest method:" /> + <TextBox Grid.Row="1" Grid.Column="1" Text="{Binding DigestMethod, Mode=OneWay}" Margin="10,2" IsReadOnly="True" /> - <Label Grid.Row="5" Grid.Column="0" Content="Digest Value read:" Style="{StaticResource DigestValueLabelStyle}" /> - <TextBox Grid.Row="5" Grid.Column="1" Text="{Binding DigestValueRead}" Margin="10,2" IsReadOnly="True"> - <TextBox.Style> - <Style TargetType="TextBox" BasedOn="{StaticResource DigestValueTextboxStyle}"> - <Style.Triggers> - <DataTrigger Binding="{Binding Valid}" Value="True"> - <Setter Property="Foreground" Value="{StaticResource Color.SuccessGreen}" /> - </DataTrigger> - <DataTrigger Binding="{Binding Valid}" Value="False"> - <Setter Property="Foreground" Value="{StaticResource Color.ErrorRed}" /> - </DataTrigger> - </Style.Triggers> - </Style> - </TextBox.Style> - </TextBox> + <Label Grid.Row="2" Grid.Column="0" Content="Digest Value read:" Style="{StaticResource DigestValueLabelStyle}" /> + <TextBox Grid.Row="2" Grid.Column="1" Text="{Binding DigestValueRead}" Margin="10,2" IsReadOnly="True"> + <TextBox.Style> + <Style TargetType="TextBox" BasedOn="{StaticResource DigestValueTextboxStyle}"> + <Style.Triggers> + <DataTrigger Binding="{Binding Valid}" Value="True"> + <Setter Property="Foreground" Value="{StaticResource Color.SuccessGreen}" /> + </DataTrigger> + <DataTrigger Binding="{Binding Valid}" Value="False"> + <Setter Property="Foreground" Value="{StaticResource Color.ErrorRed}" /> + </DataTrigger> + </Style.Triggers> + </Style> + </TextBox.Style> + </TextBox> - <Label Grid.Row="6" Grid.Column="0" Content="Digest Value computed:" Style="{StaticResource DigestValueLabelStyle}" /> - <TextBox Grid.Row="6" Grid.Column="1" Text="{Binding DigestValueComputed}" Margin="10,2" IsReadOnly="True"> - <TextBox.Style> - <Style TargetType="TextBox" BasedOn="{StaticResource DigestValueTextboxStyle}"> - <Style.Triggers> - <DataTrigger Binding="{Binding Valid}" Value="True"> - <Setter Property="Foreground" Value="{StaticResource Color.SuccessGreen}" /> - </DataTrigger> - <DataTrigger Binding="{Binding Valid}" Value="False"> + <Label Grid.Row="3" Grid.Column="0" Content="Digest Value computed:" + Style="{StaticResource DigestValueLabelStyle}" /> + <TextBox Grid.Row="3" Grid.Column="1" Text="{Binding DigestValueComputed}" Margin="10,2" IsReadOnly="True"> + <TextBox.Style> + <Style TargetType="TextBox" BasedOn="{StaticResource DigestValueTextboxStyle}"> + <Style.Triggers> + <DataTrigger Binding="{Binding Valid}" Value="True"> + <Setter Property="Foreground" Value="{StaticResource Color.SuccessGreen}" /> + </DataTrigger> + <DataTrigger Binding="{Binding Valid}" Value="False"> + <Setter Property="Foreground" Value="{StaticResource Color.ErrorRed}" /> + </DataTrigger> + </Style.Triggers> + </Style> + </TextBox.Style> + </TextBox> + </Grid> + </GroupBox> + <GroupBox Grid.Row="2" Header="Job Integrity" Style="{DynamicResource CustomGroupboxStyle}"> + <Grid> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="Auto" SharedSizeGroup="LabelsShareGroup" /> + <ColumnDefinition Width="*" /> + </Grid.ColumnDefinitions> + <Grid.RowDefinitions> + <RowDefinition /> + <RowDefinition /> + <RowDefinition /> + <RowDefinition /> + </Grid.RowDefinitions> + <Label Grid.Row="0" Grid.Column="0" Content="Job CanonicalizationMethod:" /> + <TextBox Grid.Row="0" Grid.Column="1" + Text="{Binding JobCanonicalizationMethodRead, Mode=OneWay, Converter={StaticResource CollectionConverter}}" + Margin="10,2" IsReadOnly="True" /> + + <Label Grid.Row="1" Grid.Column="0" Content="Job Digest Method:" /> + <TextBox Grid.Row="1" Grid.Column="1" Text="{Binding JobDigestMethodRead, Mode=OneWay}" + Margin="10,2" IsReadOnly="True" /> + + <Label Grid.Row="2" Grid.Column="0" Content="Job Digest Value Read:" + Style="{StaticResource DigestValueLabelStyle}" /> + <TextBox Grid.Row="2" Grid.Column="1" Text="{Binding JobDigestValueRead, Mode=OneWay}" + Margin="10,2" IsReadOnly="True"> + <TextBox.Style> + <Style TargetType="TextBox" BasedOn="{StaticResource DigestValueTextboxStyle}"> <Setter Property="Foreground" Value="{StaticResource Color.ErrorRed}" /> - </DataTrigger> - </Style.Triggers> - </Style> - </TextBox.Style> - </TextBox> + <Style.Triggers> + <DataTrigger Binding="{Binding JobDigestValid}" Value="True"> + <Setter Property="Foreground" Value="{StaticResource Color.SuccessGreen}" /> + </DataTrigger> + </Style.Triggers> + </Style> + </TextBox.Style> + </TextBox> + <Label Grid.Row="3" Grid.Column="0" Content="Job Digest Value Computed:" + Style="{StaticResource DigestValueLabelStyle}" /> + <TextBox Grid.Row="3" Grid.Column="1" Text="{Binding JobDigestValueComputed, Mode=OneWay}" + Margin="10,2" IsReadOnly="True"> + <TextBox.Style> + <Style TargetType="TextBox" BasedOn="{StaticResource DigestValueTextboxStyle}"> + <Setter Property="Foreground" Value="{StaticResource Color.ErrorRed}" /> + <Style.Triggers> + <DataTrigger Binding="{Binding JobDigestValid}" Value="True"> + <Setter Property="Foreground" Value="{StaticResource Color.SuccessGreen}" /> + </DataTrigger> + </Style.Triggers> + </Style> + </TextBox.Style> + </TextBox> + </Grid> + </GroupBox> </Grid> </DataTemplate> + <BorderGapMaskConverter x:Key="BorderGapMaskConverter" /> + + <Style x:Key="CustomGroupboxStyle" TargetType="{x:Type GroupBox}"> + <Setter Property="BorderBrush" Value="#D5DFE5" /> + <Setter Property="BorderThickness" Value="1" /> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="{x:Type GroupBox}"> + <Grid SnapsToDevicePixels="true"> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="6" /> + <ColumnDefinition Width="Auto" /> + <ColumnDefinition Width="*" /> + <ColumnDefinition Width="6" /> + </Grid.ColumnDefinitions> + <Grid.RowDefinitions> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + <RowDefinition Height="*" /> + <RowDefinition Height="6" /> + </Grid.RowDefinitions> + <Border BorderBrush="Transparent" BorderThickness="{TemplateBinding BorderThickness}" + Background="{TemplateBinding Background}" Grid.ColumnSpan="4" Grid.Column="0" CornerRadius="4" Grid.Row="1" + Grid.RowSpan="3" /> + <Border BorderBrush="White" BorderThickness="{TemplateBinding BorderThickness}" Grid.Column="0" + Grid.ColumnSpan="4" CornerRadius="2" Grid.Row="1" Grid.RowSpan="3"> + <Border.OpacityMask> + <MultiBinding ConverterParameter="7" Converter="{StaticResource BorderGapMaskConverter}"> + <Binding ElementName="Header" Path="ActualWidth" /> + <Binding Path="ActualWidth" RelativeSource="{RelativeSource Self}" /> + <Binding Path="ActualHeight" RelativeSource="{RelativeSource Self}" /> + </MultiBinding> + </Border.OpacityMask> + </Border> + <Border x:Name="Header" Grid.Column="1" Padding="3,1,3,0" Grid.Row="0" Grid.RowSpan="2"> + <ContentPresenter ContentSource="Header" RecognizesAccessKey="True" + SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" /> + </Border> + <ContentPresenter Grid.ColumnSpan="2" Grid.Column="1" Margin="{TemplateBinding Padding}" Grid.Row="2" + SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" /> + </Grid> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + </UserControl.Resources> <DockPanel> @@ -246,7 +344,7 @@ </Grid.RowDefinitions> <ScrollViewer Grid.Row="0" VerticalScrollBarVisibility="Auto" HorizontalAlignment="Stretch" - Margin="10,0,10,10" Background="{x:Static SystemColors.ControlLightBrush}"> + Margin="10,0,10,10" Background="{x:Static SystemColors.ControlLightBrush}" Grid.IsSharedSizeScope="True"> <ItemsControl ItemsSource="{Binding Files}" Name="lstInput" Margin="3"> <ItemsControl.ItemContainerStyle> @@ -328,7 +426,7 @@ <Style TargetType="ContentControl"> <Setter Property="ContentTemplate" Value="{StaticResource Icon_NOK}" /> <Style.Triggers> - <DataTrigger Binding="{Binding ManufacturerReportValid}" Value="True"> + <DataTrigger Binding="{Binding ManufacturerReport.JobDigestValid}" Value="True"> <Setter Property="ContentTemplate" Value="{StaticResource Icon_OK}" /> </DataTrigger> </Style.Triggers> @@ -349,7 +447,7 @@ <Style TargetType="ContentControl"> <Setter Property="ContentTemplate" Value="{StaticResource Icon_NOK}" /> <Style.Triggers> - <DataTrigger Binding="{Binding CustomerReportReportValid}" Value="True"> + <DataTrigger Binding="{Binding CustomerReport.JobDigestValid}" Value="True"> <Setter Property="ContentTemplate" Value="{StaticResource Icon_OK}" /> </DataTrigger> </Style.Triggers> -- GitLab