none
TextBlock Bindings Getting cleared when changing Foreground Property?

    Question

  • I was able to reproduce a strange occurrence with TextBlock bindings losing their meaning. The process is strange, but happens 10 out of 10 times.

    * Set a TextBlock Text property to some kind of binding (I use a string, the source of which is contained in the DataContext)
    * Set the same TextBlock's Foreground binding to another (I use a SolidColorBrush)

    Now, altering the Foreground backend value will work perfectly. However, if you have previously called the TextBlock's Inlines property (and enumerate through it), the next time you change the Foreground property, the Text binding will get cleared and no logner be bound! The Foreground property (among others) will continue to work.. I wonder if this is just the datacontext getting lost during the process of converting the object to a list of Runs the first time?

    Anyway, I created an extremely small repro program. Would be awesome if I can get some answers for why this happens:

    Xaml:
    <Window 
        x:Class="WpfTextBlockIssue.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window1" Height="300" Width="300"
        MouseMove="Window_MouseMove"
        AllowDrop="True"
        >
        <StackPanel>
            <TextBlock Text="Data:"/>
            <TextBlock Loaded="TextBlock_Loaded" Foreground="{Binding Foreground}" Text="{Binding Path=Test}"/>
    
            <TextBlock Text="What you type below should appear above:"/>
            <TextBox Text="{Binding Path=Test, UpdateSourceTrigger=PropertyChanged}"/>
    
            <Button Content="Change, no break" x:Name="DontBreakMe" Click="DontBreakMe_Click"/>
            <Button Content="Breakme" x:Name="BreakMe" Click="BreakMe_Click"/>
    
            <TextBlock Text="Mouse Under:"/>
            <TextBlock x:Name="mouseUnder"/>
        </StackPanel>
    </Window>
    

    Code Behind:
    using System;
    using System.ComponentModel;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Documents;
    
    
    namespace WpfTextBlockIssue
    {
        /// <summary>
        /// Interaction logic for Window1.xaml
        /// </summary>
        public partial class Window1 : Window
        {
            Data mData = new Data();
    
            public Window1()
            {
                this.DataContext = mData;
                InitializeComponent();
            }
    
            TextBlock mText = null;
            private void TextBlock_Loaded(object sender, RoutedEventArgs e)
            {
                mText = (TextBlock)sender;
            }
    
            private void BreakMe_Click(object sender, RoutedEventArgs e)
            {
                foreach (Inline i in mText.Inlines)
                {
                    i.ToString();
                }
    
                Random r = new Random(DateTime.Now.Millisecond);
                mData.Foreground = new SolidColorBrush(Color.FromRgb((byte)r.Next(255), (byte)r.Next(255), (byte)r.Next(255)));
            }
    
    
            private void DontBreakMe_Click(object sender, RoutedEventArgs e)
            {
                Random r = new Random(DateTime.Now.Millisecond);
                mData.Foreground = new SolidColorBrush(Color.FromRgb((byte)r.Next(255), (byte)r.Next(255), (byte)r.Next(255)));
            }
    
            private void Window_MouseMove(object sender, MouseEventArgs e)
            {
                mouseUnder.Text = Mouse.DirectlyOver.ToString();
            }
        }
    
        #region Data Binding
        public class Data : INotifyPropertyChanged
        {
            string mTest = "Test";
            public string Test
            {
                get { return mTest; }
                set
                {
                    mTest = value;
                    OnChange("Test");
                }
            }
    
            SolidColorBrush mForeground = new SolidColorBrush(Colors.Teal);
            public SolidColorBrush Foreground
            {
                get { return mForeground; }
                set
                {
                    if (value != null)
                        value.Freeze();
    
                    mForeground = value;
                    OnChange("Foreground");
                }
            }
    
            public event PropertyChangedEventHandler PropertyChanged;
            void OnChange(string name)
            {
                if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs(name));
            }
        }
        #endregion
    }
    

    Thursday, June 11, 2009 11:55 PM

All replies

  • To be perfectly clear, the Foreground property is changed via the Inotify class and not directly set (I haven't tried to see if that makes any differences, nor have I tried seeing if using a DependencyProperty instead of inotify makes a difference, because in either case I cannot change my code to use either of those for this case). I've currently hacked/worked around the issue by not accessing the Inlines method in my code, but now I can only accomdate one whole style per TextBlock, whereas I was previously able to access each Inline's style (used for exporting Xaml/WPF object to HTML).
    Friday, June 12, 2009 4:06 PM
  • I've been away for a bit, but am surprised no one has run across this? Seems like a huge problem... and I find it really odd that the foreground property causes this behavior.

    Thoughts?
    Monday, June 22, 2009 3:49 PM