diff --git a/ILSpy/Metadata/CoffHeaderTreeNode.cs b/ILSpy/Metadata/CoffHeaderTreeNode.cs index 35208ab74..7764ce903 100644 --- a/ILSpy/Metadata/CoffHeaderTreeNode.cs +++ b/ILSpy/Metadata/CoffHeaderTreeNode.cs @@ -24,7 +24,6 @@ using System.Windows.Data; using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Metadata; -using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.TreeNodes; using ICSharpCode.ILSpy.ViewModels; @@ -48,21 +47,22 @@ namespace ICSharpCode.ILSpy.Metadata tabPage.Title = Text.ToString(); tabPage.SupportsLanguageSwitching = false; - var dataGrid = new DataGrid { - Columns = { + var dataGrid = Helpers.PrepareDataGrid(tabPage, this); + + dataGrid.RowDetailsTemplateSelector = new CharacteristicsDataTemplateSelector("Characteristics"); + dataGrid.RowDetailsVisibilityMode = DataGridRowDetailsVisibilityMode.Collapsed; + + dataGrid.Columns.Clear(); + dataGrid.AutoGenerateColumns = false; + dataGrid.Columns.AddRange( + new[] { new DataGridTextColumn { IsReadOnly = true, Header = "Member", Binding = new Binding("Member") }, new DataGridTextColumn { IsReadOnly = true, Header = "Offset", Binding = new Binding("Offset") { StringFormat = "X8" } }, new DataGridTextColumn { IsReadOnly = true, Header = "Size", Binding = new Binding("Size") }, new DataGridTextColumn { IsReadOnly = true, Header = "Value", Binding = new Binding(".") { Converter = ByteWidthConverter.Instance } }, - new DataGridTextColumn { IsReadOnly = true, Header = "Meaning", Binding = new Binding("Meaning") }, - }, - AutoGenerateColumns = false, - CanUserAddRows = false, - CanUserDeleteRows = false, - GridLinesVisibility = DataGridGridLinesVisibility.None, - RowDetailsTemplateSelector = new CharacteristicsDataTemplateSelector(), - RowDetailsVisibilityMode = DataGridRowDetailsVisibilityMode.Visible - }; + new DataGridTextColumn { IsReadOnly = true, Header = "Meaning", Binding = new Binding("Meaning") } + } + ); var headers = module.Reader.PEHeaders; var header = headers.CoffHeader; @@ -73,54 +73,52 @@ namespace ICSharpCode.ILSpy.Metadata entries.Add(new Entry(headers.CoffHeaderStartOffset + 8, header.PointerToSymbolTable, 4, "Pointer to Symbol Table", "Always 0 in .NET executables.")); entries.Add(new Entry(headers.CoffHeaderStartOffset + 12, header.NumberOfSymbols, 4, "Number of Symbols", "Always 0 in .NET executables.")); entries.Add(new Entry(headers.CoffHeaderStartOffset + 16, (int)header.SizeOfOptionalHeader, 2, "Optional Header Size", "Size of the optional header.")); - entries.Add(new Entry(headers.CoffHeaderStartOffset + 18, (int)header.Characteristics, 2, "Characteristics", "Flags indicating attributes of the file.")); + Entry characteristics; + entries.Add(characteristics = new Entry(headers.CoffHeaderStartOffset + 18, (int)header.Characteristics, 2, "Characteristics", "Flags indicating attributes of the file.", new[] { + new BitEntry(((int)header.Characteristics & 0x0001) != 0, "<0001> Relocation info stripped from file"), + new BitEntry(((int)header.Characteristics & 0x0002) != 0, "<0002> File is executable"), + new BitEntry(((int)header.Characteristics & 0x0004) != 0, "<0004> Line numbers stripped from file"), + new BitEntry(((int)header.Characteristics & 0x0008) != 0, "<0008> Local symbols stripped from file"), + new BitEntry(((int)header.Characteristics & 0x0010) != 0, "<0010> Aggressively trim working set"), + new BitEntry(((int)header.Characteristics & 0x0020) != 0, "<0020> Large address aware"), + new BitEntry(((int)header.Characteristics & 0x0040) != 0, "<0040> Reserved"), + new BitEntry(((int)header.Characteristics & 0x0080) != 0, "<0080> Bytes of machine words are reversed (Low)"), + new BitEntry(((int)header.Characteristics & 0x0100) != 0, "<0100> 32-bit word machine"), + new BitEntry(((int)header.Characteristics & 0x0200) != 0, "<0200> Debugging info stripped from file in .DBG file"), + new BitEntry(((int)header.Characteristics & 0x0400) != 0, "<0400> If image is on removable media, copy and run from the swap file"), + new BitEntry(((int)header.Characteristics & 0x0800) != 0, "<0800> If image is on Net, copy and run from the swap file"), + new BitEntry(((int)header.Characteristics & 0x1000) != 0, "<1000> System"), + new BitEntry(((int)header.Characteristics & 0x2000) != 0, "<2000> DLL"), + new BitEntry(((int)header.Characteristics & 0x4000) != 0, "<4000> File should only be run on a UP machine"), + new BitEntry(((int)header.Characteristics & 0x8000) != 0, "<8000> Bytes of machine words are reversed (High)"), + })); dataGrid.ItemsSource = entries; - + dataGrid.SetDetailsVisibilityForItem(characteristics, Visibility.Visible); tabPage.Content = dataGrid; return true; } - private class CharacteristicsDataTemplateSelector : DataTemplateSelector + public override void Decompile(Language language, ITextOutput output, DecompilationOptions options) { - public override DataTemplate SelectTemplate(object item, DependencyObject container) - { - if (((Entry)item).Member == "Characteristics") - return MakeDataTemplate((int)((Entry)item).Value); - return new DataTemplate(); - } - - private DataTemplate MakeDataTemplate(int flags) - { - FrameworkElementFactory dataGridFactory = new FrameworkElementFactory(typeof(DataGrid)); - dataGridFactory.SetValue(DataGrid.ItemsSourceProperty, new[] { - new { Value = (flags & 0x0001) != 0, Meaning = "<0001> Relocation info stripped from file" }, - new { Value = (flags & 0x0002) != 0, Meaning = "<0002> File is executable" }, - new { Value = (flags & 0x0004) != 0, Meaning = "<0004> Line numbers stripped from file" }, - new { Value = (flags & 0x0008) != 0, Meaning = "<0008> Local symbols stripped from file" }, - new { Value = (flags & 0x0010) != 0, Meaning = "<0010> Aggressively trim working set" }, - new { Value = (flags & 0x0020) != 0, Meaning = "<0020> Large address aware" }, - new { Value = (flags & 0x0040) != 0, Meaning = "<0040> Reserved" }, - new { Value = (flags & 0x0080) != 0, Meaning = "<0080> Bytes of machine words are reversed (Low)" }, - new { Value = (flags & 0x0100) != 0, Meaning = "<0100> 32-bit word machine" }, - new { Value = (flags & 0x0200) != 0, Meaning = "<0200> Debugging info stripped from file in .DBG file" }, - new { Value = (flags & 0x0400) != 0, Meaning = "<0400> If image is on removable media, copy and run from the swap file" }, - new { Value = (flags & 0x0800) != 0, Meaning = "<0800> If image is on Net, copy and run from the swap file" }, - new { Value = (flags & 0x1000) != 0, Meaning = "<1000> System" }, - new { Value = (flags & 0x2000) != 0, Meaning = "<2000> DLL" }, - new { Value = (flags & 0x4000) != 0, Meaning = "<4000> File should only be run on a UP machine" }, - new { Value = (flags & 0x8000) != 0, Meaning = "<8000> Bytes of machine words are reversed (High)" }, - }); - dataGridFactory.SetValue(DataGrid.GridLinesVisibilityProperty, DataGridGridLinesVisibility.None); - DataTemplate template = new DataTemplate(); - template.VisualTree = dataGridFactory; - return template; - } + language.WriteCommentLine(output, "COFF Header"); } + } - public override void Decompile(Language language, ITextOutput output, DecompilationOptions options) + public class CharacteristicsDataTemplateSelector : DataTemplateSelector + { + string detailsFieldName; + + public CharacteristicsDataTemplateSelector(string detailsFieldName) { - language.WriteCommentLine(output, "COFF Header"); + this.detailsFieldName = detailsFieldName; + } + + public override DataTemplate SelectTemplate(object item, DependencyObject container) + { + if (((Entry)item).Member == detailsFieldName) + return (DataTemplate)MetadataTableViews.Instance["HeaderFlagsDetailsDataGrid"]; + return null; } } } diff --git a/ILSpy/Metadata/Helpers.cs b/ILSpy/Metadata/Helpers.cs index 5e43a8974..9d6847449 100644 --- a/ILSpy/Metadata/Helpers.cs +++ b/ILSpy/Metadata/Helpers.cs @@ -71,6 +71,8 @@ namespace ICSharpCode.ILSpy.Metadata DataGridFilter.GetFilter(view).Clear(); view.RowDetailsTemplateSelector = null; view.RowDetailsVisibilityMode = DataGridRowDetailsVisibilityMode.Collapsed; + view.EnableColumnVirtualization = true; + view.EnableRowVirtualization = true; ((MetaDataGrid)view).SelectedTreeNode = selectedNode; if (!view.AutoGenerateColumns) view.Columns.Clear(); @@ -91,9 +93,15 @@ namespace ICSharpCode.ILSpy.Metadata internal static void View_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e) { var binding = new Binding(e.PropertyName) { Mode = BindingMode.OneWay }; - e.Column = new DataGridTextColumn() { - Header = e.PropertyName, - Binding = binding + e.Column = e.PropertyType.FullName switch { + "System.Boolean" => new DataGridCheckBoxColumn() { + Header = e.PropertyName, + Binding = binding + }, + _ => new DataGridTextColumn() { + Header = e.PropertyName, + Binding = binding + } }; switch (e.PropertyName) { @@ -112,6 +120,10 @@ namespace ICSharpCode.ILSpy.Metadata case "RowDetails": e.Cancel = true; break; + case "Value" when e.PropertyDescriptor is PropertyDescriptor dp && dp.ComponentType == typeof(Entry): + binding.Path = new PropertyPath("."); + binding.Converter = ByteWidthConverter.Instance; + break; default: e.Cancel = e.PropertyName.Contains("Tooltip"); if (!e.Cancel) diff --git a/ILSpy/Metadata/MetadataTableViews.xaml b/ILSpy/Metadata/MetadataTableViews.xaml index 946c5ada4..53e6a04f3 100644 --- a/ILSpy/Metadata/MetadataTableViews.xaml +++ b/ILSpy/Metadata/MetadataTableViews.xaml @@ -7,7 +7,7 @@ xmlns:cecil="clr-namespace:Mono.Cecil;assembly=Mono.Cecil" xmlns:srm="clr-namespace:System.Reflection;assembly=System.Reflection.Metadata" xmlns:dgx="urn:tom-englert.de/DataGridExtensions"> - +