WPF DataContext works differently in seemingly identical situations

I have the following resources:

<Window.Resources> <SolidColorBrush x:Key="b" Color="{Binding B}" /> <my:C x:Key="c" Prop="{Binding Source={StaticResource b}}" /> <my:C x:Key="d" Prop="{Binding A}" /> <Ellipse x:Key="e" Fill="{Binding A}" /> <Ellipse x:Key="f"> <Ellipse.Fill> <SolidColorBrush Color="{Binding B}" /> </Ellipse.Fill> </Ellipse> </Window.Resources> 

My window has a data context declared as follows:

 <Window ... DataContext="{my:Context}" ...> 

Custom C classes and context are defined as follows:

 public class Context : MarkupExtension { public Brush A { get; } = Brushes.Blue; public Color B { get; } = Colors.Red; public override object ProvideValue(IServiceProvider serviceProvider) => this; } public class C : DependencyObject { public static readonly DependencyProperty PropProperty = DependencyProperty.Register("Prop", typeof(Brush), typeof(C)); public Brush Prop { get { return (Brush)GetValue(PropProperty); } set { SetValue(PropProperty, value); } } } 

Now the ways that I use my context and data binding look very similar to me, but if I check my resources for the following code (inside the button click handler)

 MessageBox.Show("f: " + ((FindResource("f") as Ellipse).Fill?.ToString() ?? "null")); MessageBox.Show("e: " + ((FindResource("e") as Ellipse).Fill?.ToString() ?? "null")); MessageBox.Show("d: " + ((FindResource("d") as C).Prop?.ToString() ?? "null")); MessageBox.Show("c: " + ((FindResource("c") as C).Prop?.ToString() ?? "null")); MessageBox.Show("b: " + (FindResource("b") as SolidColorBrush).Color.ToString()); 

I get this result:

 f: #00FFFFFF e: null d: null c: #FFFF0000 b: #FFFF0000 

i.e. only the last two seem correct. What could be the reason for this?

+5
source share
2 answers

It’s strange.

my: C obviously does not have a DataContext and therefore cannot directly communicate with anything.

Resources with a DataContext do not inherit the owner of the DataContext resources (Ellipses e and f)

SolidColorBrush "b" displays the System.Windows.Freezable form, which has a protected field / property called InheritanceContext, which for "b" is set to MainWindow. I think he has access to Context.B through this link and that why "b" and "c" show the correct color.

+1
source

It was interesting to me, and I decided to play a little with him. I have never been an XAML expert, but I wanted to share my findings, if at all.

I added the following XAML to the Grid on the page:

 <Ellipse Fill="{StaticResource b}" /> <Ellipse Grid.Row="1" Fill="{Binding Source={StaticResource c}, Path=Prop}" /> <Ellipse Grid.Row="2" Fill="{Binding Source={StaticResource d}, Path=Prop}" /> <ContentControl Grid.Row="3" Content="{StaticResource e}" /> <ContentControl Grid.Row="4" Content="{StaticResource f}" /> 

Here is a screenshot of the results:

Elliptical screen shot

The following binding error appeared in the Output window, which, it seems to me, explains why d not populated:

System.Windows.Data error: 2: Cannot find the FrameworkElement or FrameworkContentElement control for the target element. BindingExpression: Path = A; DataItem = NULL; target element is 'C' (HashCode = 60275915); target property - "Prop" (type "Brush")

It looks like there might be a problem with the binding solution for d , since it cannot find its position in the hierarchy of elements and therefore cannot resolve the DataContext.

I also noticed that if I commented on XAML, the behavior was the same as in the question. Both e and d were empty. Based on this, it seems that the use of resources can affect whether binding can be enabled at run time.

It would be great to hear from someone a deeper understanding of the inner workings of how bindings function in resources.

0
source

Source: https://habr.com/ru/post/1258291/


All Articles