Repository: AvaloniaUI/Avalonia
File: src/Avalonia.Controls/TabControl.cs (C#)

Code before:
                    if (SelectedContentTemplate != SelectContentTemplate(container.GetValue(ContentTemplateProperty)))
                    {
                        // If the value of SelectedContentTemplate is about to change, clear it first. This ensures
                        // that the template is not reused as soon as SelectedContent changes in the statement below
                        // this block, and also that controls generated from it are unloaded before SelectedContent
                        // (which is typically their DataContext) changes.
                        SelectedContentTemplate = null;
                    }

                    _selectedItemSubscriptions = new CompositeDisposable(
                        container.GetObservable(ContentControl.ContentProperty).Subscribe(content =>
                        {
                            var contentElement = content as StyledElement;
                            var contentDataContext = contentElement?.DataContext;
                            SelectedContent = content;

                            // Reset the TabItem Content's DataContext since it gets set to TabControl's DataContext
                            // when SelectedContent is set to TabItem's Content. Happens when the content's parent
                            // is set to ContentPart (ContentPresenter) and the DataContext property is inherited.
                            if (contentElement is not null &&
                                contentElement.DataContext != contentDataContext)
                            {
                                // Unfortunately this forces the property to go from inherited to set with local
                                // priority
                                Debug.Assert(!contentElement.IsSet(DataContextProperty));
                                contentElement.DataContext = contentDataContext;
                            }
                        }),
                        container.GetObservable(ContentControl.ContentTemplateProperty).Subscribe(v => SelectedContentTemplate = SelectContentTemplate(v)));

                    // Note how we fall back to our own ContentTemplate if the container doesn't specify one
                    IDataTemplate? SelectContentTemplate(IDataTemplate? containerTemplate) => containerTemplate ?? ContentTemplate;
                }
            }
        }

        /// <summary>
        /// Called when an <see cref="ContentPresenter"/> is registered with the control.
        /// </summary>
        /// <param name="presenter">The presenter.</param>
        protected virtual bool RegisterContentPresenter(ContentPresenter presenter)
        {
            if (presenter.Name == "PART_SelectedContentHost")
            {
                ContentPart = presenter;
                return true;
            }

            return false;
        }


Review comment (bug):
```suggestion
                                Debug.Assert(!contentElement.IsSet(DataContextProperty));
                                if (contentElement.Parent is not null)
                                {
                                    // Best approximation of an inherited property
                                    contentElement.Bind(DataContextProperty,
                                        contentElement.Parent.GetBindingObservable(DataContextProperty),
                                        BindingPriority.Inherited);
                                }
                                else
                                {
                                    // Unfortunately this forces the property to go from inherited to set with local
                                    // priority
                                    contentElement.DataContext = contentDataContext;
                                }
```

Maybe rather than setting the value directly, an inheritance can be approximated by binding to the logical parent's DataContext directly.

Code after:
                        // (which is typically their DataContext) changes.
                        SelectedContentTemplate = null;
                    }

                    _selectedItemSubscriptions = new CompositeDisposable(
                        container.GetObservable(ContentControl.ContentProperty).Subscribe(content =>
                        {
                            var contentElement = content as StyledElement;
                            var contentDataContext = contentElement?.DataContext;
                            SelectedContent = content;

                            // When the ContentPresenter (ContentPart) displays content that is a Control, it doesn't
                            // set its DataContext to that of the Control's. If the content doesn't set a DataContext,
                            // then it gets inherited from the TabControl. Work around this issue by setting the
                            // DataContext of the ContentPart to the content's original DataContext (inherited from
                            // container).
                            if (contentElement is not null &&
                                contentElement.DataContext != contentDataContext &&
                                ContentPart is not null)
                            {
                                Debug.Assert(!contentElement.IsSet(DataContextProperty));
                                ContentPart.DataContext = contentDataContext;
                            }
                        }),
                        container.GetObservable(ContentControl.ContentTemplateProperty).Subscribe(v => SelectedContentTemplate = SelectContentTemplate(v)));

                    // Note how we fall back to our own ContentTemplate if the container doesn't specify one
                    IDataTemplate? SelectContentTemplate(IDataTemplate? containerTemplate) => containerTemplate ?? ContentTemplate;
                }
            }
        }

        /// <summary>
        /// Called when an <see cref="ContentPresenter"/> is registered with the control.
        /// </summary>
        /// <param name="presenter">The presenter.</param>
        protected virtual bool RegisterContentPresenter(ContentPresenter presenter)
        {
            if (presenter.Name == "PART_SelectedContentHost")
            {
                ContentPart = presenter;
                return true;
            }

            return false;
        }

        protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
        {
            ItemsPresenterPart = e.NameScope.Find<ItemsPresenter>("PART_ItemsPresenter");
            ItemsPresenterPart?.ApplyTemplate();