Resolved SetBinding (Code Behind) does not work, TextBlock.Text is deleted

AnnaBauer21

Member
Joined
Nov 29, 2024
Messages
7
Programming Experience
3-5
I created a small test project to simply illustrate my problem.

The following process:

  1. I have a TextBlock in the XAML with a binding to a RelativSource.
  2. In the code behind, highlighting information is added to the Inlines of the TextBlock
  3. Because of DataGrid with VirtualizingStackPanel.VirtualizationMode="Recycling" the result of GetBindingExpression(TextBlock.TextProperty) is null in the event DataGrid.OnLoadingRow but also in the event DataGridRow.Loaded
  4. Now I tried to reset the binding
  5. But this replaces the text in the TextBlock with the default value ("") instead of using the correct text based on the binding.
I hope you can help me so that the text is there after setting the binding.

XAML
XML:
<StackPanel Tag="{Binding Path=MissionName, Converter={StaticResource DebugConverter}}">
    <TextBlock
        Text="{Binding Path=Tag, RelativeSource={RelativeSource AncestorType=StackPanel}" />
</StackPanel>


Code Behind
C#:
// Save data for binding
var exp = txtBlock.GetBindingExpression(TextBlock.TextProperty);
txtBlock.Tag = new Tuple<RelativeSource, PropertyPath>(exp.ParentBinding.RelativeSource, exp.ParentBinding.Path)


var inlines = new List<Inline>();
inlines.Add(new Run(text.Substring(0, 1)));
inlines.Add(new Run(text.Substring(1, 2))
        {
            Background = filterData.SelectionColor,
            Foreground = filterData.ForegroundColor
        });
inlines.Add(new Run(text.Substring(3, 1)));

txtBlock.Inlines.Clear();
txtBlock.Inlines.AddRange(inlines);


In Event
C#:
var tagData = (Tuple<RelativeSource, PropertyPath>) txtBlock.Tag;

var binding = new Binding { RelativeSource = tagData.Item1, Path = tagData.Item2};
txtBlock.SetBinding(TextBlock.TextProperty, binding);    // <- txtBlock.Text now is ""


// This call says now, IsDirty="true" & Status="Unattached"
var exp = txtBlock.GetBindingExpression(TextBlock.TextProperty);


I hope you have an idea.

I know it doesn't correspond to MVVM, but I'm currently trying to get it to work.

Thank you all

Kind regards
 
Solution
Hello,
I found a solution.

I'm in the "LoadingRow" event of the DataGrid.

The binding is updated, but the row is currently "loading", so I don't see any changes in the text.

After setting the binding, I now call a method with BeginInvoke DispatcherPriority.Loaded that should perform the highlighting.
In this method, the row is loaded and the TextBlocks contains the correct text.
My suspicion is that the line:
C#:
var binding = new Binding { RelativeSource = tagData.Item1, Path = tagData.Item2};
doesn't provide enough information or context for the created Binding object.

Just guessing: Perhaps the BindingExpresssion.ResolvedSource also needs to set on the Binding.Source?

As an aside: Great job applying your hyper-focus to dive into setting breakpoints and looking at various with the debugger! If you have the patience, perhaps look in referencesource.microsoft.com or source.dot.net at the source code for BindingExpression and Binding or Framework.SetBinding() to try to see what is happenig under the covers.
 
Hello,
I found a solution.

I'm in the "LoadingRow" event of the DataGrid.

The binding is updated, but the row is currently "loading", so I don't see any changes in the text.

After setting the binding, I now call a method with BeginInvoke DispatcherPriority.Loaded that should perform the highlighting.
In this method, the row is loaded and the TextBlocks contains the correct text.
 
Solution
So it's something like a two phase update where all the changes do not get applied until after the "loaded" event. Semantically, it makes sense. Just kind of weird that it's surprising that any changes you do imperatively are just queued for work later. I wonder if that behavior is documented officially, or it's just in some dev's obscure blog post somewhere.

Anyway, great job making use of your strengths to dig in and find the cause of the problem and find a solution!
 
Back
Top Bottom