private void this_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e) { // Reset the column organization. // This should be useless under the current scenario. foreach (var dc in dataGrid.Columns.Except(StandardColumns.Select(sc => sc.Column)).ToList()) { dataGrid.Columns.Remove(dc); } foreach (var dc in dataGrid.Columns) { dc.SetValue(ColumnInUseProperty, false); } // Our DataContext should always be an ITable, but null should be allowed (though we don't need.) var table = e.NewValue as ITableController; if (table == null) { return; } // Show / hide standard columns. // Unused standard columns are kept in the list, but users can't view them. // We use a false value of ColumnInUse atatched property to tell the case. foreach (var colInfo in StandardColumns) { var in_use = table.AllRows.Any(colInfo.InUse); colInfo.Column.Visibility = in_use ? Visibility.Visible : Visibility.Collapsed; colInfo.Column.SetValue(ColumnInUseProperty, in_use); } // A special handling of Asset column visibility. // There are many cases that a file contains only one Asset, // and Asset column is just redundant in the cases, so hide it in the cases. // (but users can still view it if they want.) if (Asset.Visibility == Visibility.Visible && Asset2.Visibility != Visibility.Visible && !table.AllRows.Select(r => r.Asset).Distinct().Skip(1).Any()) { Asset.Visibility = Visibility.Collapsed; } // Yet another special handling of TagList column visibility. // It is always hidden initially. TagList.Visibility = Visibility.Collapsed; // Create columns for additional properties. // Their initial shown/hidden states are specified by the DOC module via AdditionalProps. // ColumnInUse attached property is always set to true so that users can view any column. // We don't check whether an additonal property is actually used; // If such a checking is essential for a particular additional property, // the responsible AssetReader can do it when constructing the Properties. // See TableController.cs for the interaction between the AssetReader and TableController.AdditionalProps. foreach (var props in table.AdditionalProps) { var column = new DataGridTextColumn() { Header = props.Key.Replace("_", " "), // XXX: No, we should not do this! Binding = new Binding("[" + props.Index + "]"), Visibility = props.Visible ? Visibility.Visible : Visibility.Collapsed, ElementStyle = FindResource("AdditionalColumnElementStyle") as Style, }; column.SetValue(ColumnInUseProperty, true); dataGrid.Columns.Add(column); } // Set FilterOptions attached property to all in-use columns. foreach (var column in dataGrid.Columns.Where(GetColumnInUse)) { var grabber = CreateGrabber(column.SortMemberPath); var list = table.AllRows.Select(grabber).Distinct().OrderBy(s => string.IsNullOrEmpty(s) ? 0 : 1).ThenBy(s => s).Select(s => FilterOption.Get(s)); column.SetValue(FilterOptionsProperty, list); } }
private void UpdateColumns() { var table = DataContext as ITableController; if (table == null) { return; } // Use/unuse standard columns. // Unused standard columns are kept in the list, but users can't view them. // We use a false value of ColumnInUse atatched property to tell the case. // Unused (ColumnInUse == false) columns can be used (ColumnInUse == true) in future reloading. // Once used, however, a column will never get back to Unused status. foreach (var colInfo in StandardColumns) { if (!GetColumnInUse(colInfo.Column) && table.AllRows.Any(colInfo.InUse)) { SetColumnInUse(colInfo.Column, true); } } // Create columns for additional properties. // Their initial shown/hidden states are specified by the DOC module via AdditionalProps. // ColumnInUse attached property is always set to true so that users can view any column. // We don't check whether an additonal property is actually used; // If such a checking is essential for a particular additional property, // the responsible AssetReader can do it when constructing the Properties. // See TableController.cs for the interaction between the AssetReader and TableController.AdditionalProps. foreach (var props in table.AdditionalProps) { var path = "[" + props.Index + "]"; // Don't add a duplicate column. if (dataGrid.Columns.Any(col => ((col as DataGridTextColumn)?.Binding as Binding)?.Path?.Path == path)) { continue; } var column = new DataGridTextColumn() { Header = props.Key.Replace("_", " "), // XXX: No, we should not do this! Binding = new Binding(path), Visibility = props.Visible ? Visibility.Visible : Visibility.Collapsed, ElementStyle = FindResource("AdditionalColumnElementStyle") as Style, }; column.SetValue(ColumnInUseProperty, true); // a sort of a hack to avoid a few columns (containing some very long text) to occupy the entire space. // The following code includes several magic numbers that were determined without grounds. FIXME. if (table.AllRows.Take(100) .Select(row => row[props.Index]) .Any(text => text?.Length > 50 || text?.IndexOf('\n') >= 0)) { column.Width = DataGridLengthStar; } dataGrid.Columns.Add(column); } // Set FilterOptions attached property to all in-use columns. foreach (var column in dataGrid.Columns.Where(GetColumnInUse)) { var grabber = CreateGrabber(column.SortMemberPath); var list = table.AllRows.Select(grabber).Distinct().OrderBy(s => string.IsNullOrEmpty(s) ? 0 : 1).ThenBy(s => s).Select(s => FilterOption.Get(s)); column.SetValue(FilterOptionsProperty, list); } }