0

Alright so I want to bind the Foreground property of a TextBlock control to a property in the codebehind of the MainWindow. The control is on a page which is loaded in a frame on the MainWindow. I have tried a few things, but the binding I would think should work, as demonstrated, does not.

The mainwindow and Page xaml:

<MainWindow>
    <Frame></Frame>
</MainWindow>

<Page>
    <TextBlock Foreground="{Binding RelativeSource={
        RelativeSource FindAncestor, AncestorType={
        x:Type local:MainWindow}}, Path=TextBrush}" />
    <!-- or Foreground="{Binding TextBrush, RelativeSource={
        RelativeSource FindAncestor, AncestorType={
        x:Type local:MainWindow}}}" /> -->
</Page>

And the mainwindow codebehind:

public partial class MainWindow : INotifyPropertyChanged {
private Brush _textBrush;
public Brush TextBrush
    {
        get => _textBrush;
        set
        {
            _textBrush = value;
            OnPropertyChanged("TextBrush");
        }
    }

public ICommand SwitchToDarkmodeCommand
    {
        get
        {
            return new DelegateCommand(() =>
            {
                TextBrush = Brushes.White;
                BackgroundBrush = (Brush)new BrushConverter().ConvertFromString("#D2D2D2");
            });
        }
    }

It seems way too simple. What am I doing wrong here?

Edit: the output. Good point.

System.Windows.Data Error: 4 : Cannot find source for binding with reference 
'RelativeSource FindAncestor, AncestorType='AddINDesignerWPF.MainWindow', AncestorLevel='1''. 
BindingExpression:Path=TextBrush; DataItem=null; target element is 'TextBlock' (Name=''); 
target property is 'Foreground' (type 'Brush')
NullError
  • 71
  • 2
  • 11

2 Answers2

0

try to use dependency property instead of normal property:

  public static readonly DependencyProperty TextBrushProperty =
  DependencyProperty.Register("TextBrush", typeof(Brush), typeof(MainWindow), new UIPropertyMetadata());

public Brush TextBrush
{
    get { return (Brush)this.GetValue(TextBrushProperty); }
    set { this.SetValue(TextBrushProperty, value); }
}
Luke
  • 58
  • 6
0

I just spent some time looking through decompiled WPF code, the reason why the binding fails is that the visual tree somehow stops right before the frame when walking up from the TextBlock in the Page. Thus, the RelativeSource binding with FindAncestor cannot find the source property, no matter whether it is a dependency or INPC property, and no matter whether you use Window or MainWindow as Type.

The reason for this behavior probably is that the frame control isolates its content from the rest of the application, since it is meant for external content you might not trust. This SO post gives some more information, and also offers a solution how to pass the data context to the page in the frame.

That said, the solution for you might be not to use a Frame/Page at all, depending on what you want to achieve in the first place.

MaSiMan
  • 655
  • 6
  • 16