I have a hierarchical dataset bound as the datasource to a datagrid. The rows in the parent table show up in the grid, and all the rows have an expansion indicator on their left. However, some of the rows in my datasource do not have corresponding rows in the child table. For these, I don't want the expansion indicator to appear, so that the user can easily tell which rows have children and which do not. Is this possible?
thanks,
- Kam
I just figured this out, and figure I'd post it here in case anyone else was interested:
Handle the InitializeRecord event, and in your handler set the Record's ExpansionIndicatorVisibility propery according:
e.g.
private void OnInitializeRecord(object sender, InitializeRecordEventArgs e) { if (e.Record != null) { if (e.Record.HasChildren) e.Record.ExpansionIndicatorVisibility = Visibility.Visible; else e.Record.ExpansionIndicatorVisibility = Visibility.Hidden; }
}
I was excited about this post, but I've since had to remove this trick from my code. I found that while it helped under some situations (where the indicator was falsely appearing), it actually CAUSED the indicator to appear in other situations (where there was no indicator).
In other words, on my child tables, I was seeing an extra layer of "+" when NOTHING should have appeared.
I haven't had time to investigate this, but I suspect an additional check of some sort is required in the above code snippet to detect whether the property should be manipulated at all. If anyone has some insight, I'd like to hear it, because I have all sorts of "+" symbols where there are no children, which is yucky.
I recently noticed the extra "+"'s too. Commenting out the line that sets it to visible seems to work for me now, though I haven't tested this extensively. Not sure why some of those child records would return true for HasChildren when they don't really have children.
private void OnInitializeRecord(object sender, InitializeRecordEventArgs e) { if (e.Record != null) { if (e.Record.HasChildren) ;//e.Record.ExpansionIndicatorVisibility = Visibility.Visible; else e.Record.ExpansionIndicatorVisibility = Visibility.Hidden; } }
I have been plugging away at this for a day and have come up with the following. I had real issues with this since I want to move records around and make the parent and child relationships different. Even though the code mentioned above worked after initial load, it didn't work for updates. Here what I came up with in addition to the code mentioned in the previous post.
void theDataGrid_RecordUpdated(object sender, RecordUpdatedEventArgs e) { Record parent = theDataGrid.Records[0] as Record;
if (parent.HasChildren) { parent.ResetExpansionIndicatorVisibility(); SetExpansionIndicator(parent); } else { parent.ExpansionIndicatorVisibility = Visibility.Hidden; } }
private void SetExpansionIndicator(Record parentDataRecord) { if (parentDataRecord.GetType() == typeof(DataRecord)) { DataRecord dr = parentDataRecord as DataRecord;
foreach (ExpandableFieldRecord child in dr.ChildRecords) { if (child.HasChildren) { child.ResetExpansionIndicatorVisibility(); SetExpansionIndicator(child as Record); } else { child.ExpansionIndicatorVisibility = Visibility.Hidden; } } }
if (parentDataRecord.GetType() == typeof(ExpandableFieldRecord)) { ExpandableFieldRecord dr = parentDataRecord as ExpandableFieldRecord; foreach (Record child in dr.ChildRecords) { if (child.HasChildren) { child.ResetExpansionIndicatorVisibility(); SetExpansionIndicator(child as Record); } else { child.ExpansionIndicatorVisibility = Visibility.Hidden; } } } }
As a note Joe and Sandip... I consider this a bug. Is this being looked at as a possible hotfix? Expansion Indicators should automatically detect if child records are present and be visible. If no child records, then the indicator should not be visible.
Thanks,
Rod
I used the following code
If e.Record IsNot Nothing Then
e.Record.ExpansionIndicatorVisibility = Visibility.Visible
Else
e.Record.ExpansionIndicatorVisibility = Visibility.Hidden
End If
and get a " Message="Object reference not set to an instance of an object." Source="Infragistics3.Wpf.DataPresenter.v9.1"" error when I expand a parent (my hierarchy has two levels and not all of the top level has children).
Any ideas?
Can you provide the callstack for the exception? It would also be helpful if can you post a project that demonstrates the issue.
JohnFrench said: Here is the call stack
Andrew, I can't post the project but here is my grid definition
="xamDataGridOL_InitializeRecord">
</
igDP:XamDataGrid>
I am using code very similar to the article "Binding to a Hierarchical SQL Database" to source my data i.e.
flatData = New DataSet("flatData")
sqlConnection1 =
New SqlConnection("Data Source=BIOVPC;Initial Catalog=" & _
"DarwinApp;Integrated Security=True")
sqlSelectCommand1 =
New SqlCommand("SELECT KeyPrefix,ObjTypeDescr," & _
"CAST(ObjTypeID AS INT) " & _"AS aTypeID FROM ObjectType ORDER BY ObjTypeDescr")
sqlSelectCommand1.Connection = sqlConnection1
sqlDataAdapter1 =
New SqlDataAdapter
sqlDataAdapter1.SelectCommand = sqlSelectCommand1
sqlConnection2 =
sqlSelectCommand2 =
New SqlCommand("SELECT ObjKey,ObjName,CAST(ObjTypeID AS INT) "
& _"AS bTypeID FROM ObjectLibrary ORDER BY ObjName")
sqlSelectCommand2.Connection = sqlConnection2
sqlDataAdapter2 =
sqlDataAdapter2.SelectCommand = sqlSelectCommand2
sqlDataAdapter1.Fill(flatData.Tables.Add(
"ObjTypes"))
sqlDataAdapter2.Fill(flatData.Tables.Add(
"ObjLibrary"))
tblRelation =
New DataRelation("Hierarchy", _flatData.Tables("ObjTypes").Columns("aTypeID"), _
flatData.Tables(
"ObjLibrary").Columns("bTypeID"))
flatData.Relations.Add(tblRelation)
Me.xamDataGridOL.DataSource = flatData.Tables(0).DefaultView
note that there are a few line continuation characters out of place in the above (cut and paste issues).
In the FieldLayoutInitialized Event Handler I have the following
e.FieldLayout.Fields(
"aTypeID").Visibility = Visibility.Hidden
and am just trying to work out how to hide the bTypeID column!
I am new to your controls if that has any bearing on the issue. .
Here is the call stack
at System.RuntimeMethodHandle._InvokeMethodFast(Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner) at System.RuntimeMethodHandle.InvokeMethodFast(Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks) at System.Delegate.DynamicInvokeImpl(Object[] args) at System.Windows.RoutedEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget) at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target) at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs) at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised) at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args) at System.Windows.UIElement.RaiseEvent(RoutedEventArgs e) at Infragistics.Windows.DataPresenter.DataPresenterBase.OnInitializeRecord(InitializeRecordEventArgs args) at Infragistics.Windows.DataPresenter.DataPresenterBase.RaiseInitializeRecord(Record record) at Infragistics.Windows.DataPresenter.Record.FireInitializeRecord() at Infragistics.Windows.DataPresenter.MainRecordSparseArray.OnItemCreated(Object item, Int32 index) at Infragistics.Windows.Helpers.SparseArray.CreateItemHelper(ICreateItemCallback createItemCallback, Node node, Int32 nodeIndex, Int32 overallIndex) at Infragistics.Windows.Helpers.SparseArray.GetItemAtVisibleIndex(Int32 visibleIndex, ICreateItemCallback createItemCallback) at Infragistics.Windows.DataPresenter.MainRecordSparseArray.GetItemAtVisibleIndex(Int32 visibleIndex) at Infragistics.Windows.DataPresenter.ViewableRecordCollection.GetItem(Int32 index) at Infragistics.Windows.DataPresenter.ViewableRecordCollection.VisualRecordEnumerator.MoveNext() at System.Windows.Data.CollectionView..ctor(IEnumerable collection, Int32 moveToFirst) at System.Windows.Data.ListCollectionView..ctor(IList list) at MS.Internal.Data.ViewManager.GetViewRecord(Object collection, CollectionViewSource cvs, Type collectionViewType, Boolean createView) at MS.Internal.Data.DataBindEngine.GetViewRecord(Object collection, CollectionViewSource key, Type collectionViewType, Boolean createView) at System.Windows.Data.CollectionViewSource.GetDefaultCollectionView(Object source, Boolean createView) at System.Windows.Data.CollectionViewSource.GetDefaultCollectionView(Object source, DependencyObject d) at System.Windows.Controls.ItemCollection.SetItemsSource(IEnumerable value) at System.Windows.Controls.ItemsControl.OnItemsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) at System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e) at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e) at Infragistics.Windows.Virtualization.RecyclingItemsControl.OnPropertyChanged(DependencyPropertyChangedEventArgs e) at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args) at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, OperationType operationType) at System.Windows.DependencyObject.SetValueCommon(DependencyProperty dp, Object value, PropertyMetadata metadata, Boolean coerceWithDeferredReference, OperationType operationType, Boolean isInternal) at System.Windows.DependencyObject.SetValue(DependencyProperty dp, Object value) at System.Windows.Data.BindingOperations.SetBinding(DependencyObject target, DependencyProperty dp, BindingBase binding) at System.Windows.FrameworkElement.SetBinding(DependencyProperty dp, BindingBase binding) at Infragistics.Windows.DataPresenter.DataPresenterBase.InitializeRecordListControlPanel(RecordListControl rlc, Type panelType) at Infragistics.Windows.DataPresenter.DataPresenterBase.InitializeItemsPanel() at Infragistics.Windows.DataPresenter.DataPresenterBase.InitializeRecordManagerDataSource() at Infragistics.Windows.DataPresenter.DataPresenterBase.get_CurrentRecordListControl() at Infragistics.Windows.DataPresenter.DataPresenterBase.VerifyContentSiteGrid() at Infragistics.Windows.DataPresenter.DataPresenterBase.OnApplyTemplate() at System.Windows.FrameworkElement.ApplyTemplate() at System.Windows.FrameworkElement.MeasureCore(Size availableSize) at System.Windows.UIElement.Measure(Size availableSize) at MS.Internal.Helper.MeasureElementWithSingleChild(UIElement element, Size constraint) at System.Windows.Controls.ContentPresenter.MeasureOverride(Size constraint) at System.Windows.FrameworkElement.MeasureCore(Size availableSize) at System.Windows.UIElement.Measure(Size availableSize) at System.Windows.Controls.DockPanel.MeasureOverride(Size constraint) at System.Windows.FrameworkElement.MeasureCore(Size availableSize) at System.Windows.UIElement.Measure(Size availableSize) at System.Windows.Controls.Border.MeasureOverride(Size constraint) at System.Windows.FrameworkElement.MeasureCore(Size availableSize) at System.Windows.UIElement.Measure(Size availableSize) at System.Windows.Controls.Control.MeasureOverride(Size constraint) at System.Windows.FrameworkElement.MeasureCore(Size availableSize) at System.Windows.UIElement.Measure(Size availableSize) at System.Windows.Controls.StackPanel.MeasureOverride(Size constraint) at System.Windows.FrameworkElement.MeasureCore(Size availableSize) at System.Windows.UIElement.Measure(Size availableSize) at MS.Internal.Helper.MeasureElementWithSingleChild(UIElement element, Size constraint) at System.Windows.Controls.ContentPresenter.MeasureOverride(Size constraint) at System.Windows.FrameworkElement.MeasureCore(Size availableSize) at System.Windows.UIElement.Measure(Size availableSize) at System.Windows.ContextLayoutManager.UpdateLayout() at System.Windows.ContextLayoutManager.UpdateLayoutCallback(Object arg) at System.Windows.Media.MediaContext.InvokeOnRenderCallback.DoWork() at System.Windows.Media.MediaContext.FireInvokeOnRenderCallbacks() at System.Windows.Media.MediaContext.RenderMessageHandlerCore(Object resizedCompositionTarget) at System.Windows.Media.MediaContext.RenderMessageHandler(Object resizedCompositionTarget) at System.Windows.Media.MediaContext.Resize(ICompositionTarget resizedCompositionTarget) at System.Windows.Interop.HwndTarget.OnResize() at System.Windows.Interop.HwndTarget.HandleMessage(Int32 msg, IntPtr wparam, IntPtr lparam) at System.Windows.Interop.HwndSource.HwndTargetFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled) at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled) at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o) at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Boolean isSingleParameter) at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler) at System.Windows.Threading.Dispatcher.WrappedInvoke(Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler) at System.Windows.Threading.Dispatcher.InvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Boolean isSingleParameter) at System.Windows.Threading.Dispatcher.Invoke(DispatcherPriority priority, Delegate method, Object arg) at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam) at MS.Win32.UnsafeNativeMethods.CallWindowProc(IntPtr wndProc, IntPtr hWnd, Int32 msg, IntPtr wParam, IntPtr lParam) at MS.Win32.HwndSubclass.DefWndProcWrapper(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam) at MS.Win32.UnsafeNativeMethods.CallWindowProc(IntPtr wndProc, IntPtr hWnd, Int32 msg, IntPtr wParam, IntPtr lParam) at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam) at Infragistics.Windows.Ribbon.NativeWindowMethods.SetWindowRgn(IntPtr hWnd, IntPtr hRgn, Boolean bRedraw) at Infragistics.Windows.Ribbon.NativeWindowMethods.SetWindowRgnApi(IntPtr hWnd, IntPtr hRgn, Boolean bRedraw) at Infragistics.Windows.Ribbon.XamRibbonWindow.UpdateWindowClipRegion(IntPtr newRegion) at Infragistics.Windows.Ribbon.XamRibbonWindow.UpdateWindowClipRegion() at Infragistics.Windows.Ribbon.XamRibbonWindow.OnSourceInitialized(EventArgs e) at System.Windows.Window.CreateSourceWindowImpl() at System.Windows.Window.SafeCreateWindow() at System.Windows.Window.ShowHelper(Object booleanBox) at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Boolean isSingleParameter) at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler) at System.Windows.Threading.Dispatcher.WrappedInvoke(Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler) at System.Windows.Threading.DispatcherOperation.InvokeImpl() at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state) at System.Threading.ExecutionContext.runTryCode(Object userData) at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Windows.Threading.DispatcherOperation.Invoke() at System.Windows.Threading.Dispatcher.ProcessQueue() at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled) at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled) at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o) at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Boolean isSingleParameter) at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler) at System.Windows.Threading.Dispatcher.WrappedInvoke(Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler) at System.Windows.Threading.Dispatcher.InvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Boolean isSingleParameter) at System.Windows.Threading.Dispatcher.Invoke(DispatcherPriority priority, Delegate method, Object arg) at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam) at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg) at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame) at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame) at System.Windows.Threading.Dispatcher.Run() at System.Windows.Application.RunDispatcher(Object ignore) at System.Windows.Application.RunInternal(Window window) at System.Windows.Application.Run(Window window) at System.Windows.Application.Run() at DarwinWPF.Application.Main() at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args) at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() at System.Threading.ThreadHelper.ThreadStart_Context(Object state) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ThreadHelper.ThreadStart()
Let me know if you need anything else.
Thanks
John