Why is the DataBinding on my Windows.Media.brush not working?

Notch_Over_Heaven 1 Reputation point
2020-03-26T04:10:07.433+00:00

I ran into a strange error

This is the control

<UserControl x:Class="PHOWjection_Software_3._0.CustomControls.LyricsDisplay"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:local="clr-namespace:PHOWjection_Software_3._0.CustomControls"
             mc:Ignorable="d" Background="White"
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid>
        <ListView x:Name="View" Grid.Row="1" Foreground="Black" ScrollViewer.HorizontalScrollBarVisibility="Disabled" BorderThickness="0" ScrollViewer.CanContentScroll="True">
            <ListView.View>
                <GridView x:Name="ViewGridView">
                    <GridViewColumn Header="HI" Width="30">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <Grid Background="{Binding HeaderBGBrush}">
                                    <!--<Rectangle Fill="{Binding HeaderBrush}" />-->
                                    <TextBlock Text="{Binding HeaderIcon}" Foreground="{Binding HeaderFGBrush}" HorizontalAlignment="Center" Tag="{Binding Identity}" />
                                </Grid>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                    <GridViewColumn Header="Abbreviation" Width="500">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding Block_OneLine}" Tag="{Binding Identity}" />
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                </GridView>
            </ListView.View>
            <ListView.ItemContainerStyle>
                <Style TargetType="{x:Type ListViewItem}">
                    <Setter Property="HorizontalContentAlignment" Value="Stretch" />
                    <Setter Property="VerticalContentAlignment" Value="Stretch" />
                </Style>
            </ListView.ItemContainerStyle>
        </ListView>
    </Grid>
</UserControl>

Here is the code behind

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using PHOWjection_Software_3._0.ItemType;

namespace PHOWjection_Software_3._0.CustomControls
{
    public partial class LyricsDisplay : UserControl
    {
        public LyricsDisplay()
        {
            InitializeComponent();
        }

        public void Display(Song Song)
        {
            View.Items.Clear();
            foreach (Lyrics_Block LB in Song.Lyrics_Blocks)
            {
                View.Items.Add(LB);
            }
            //Song.Lyrics_Blocks.ForEach(x => View.Items.Add(x));
        }
    }
}

Here is the Code for Song and Lyrics_Block (the class being added to the listview)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
using System.Windows;
using System.Windows.Media;
using System.Windows.Controls;
using System.Threading;
using System.Globalization;

namespace PHOWjection_Software_3._0.ItemType
{
    public partial class Song : DataBaseItem
    {
        public Song Identity { get { return this; } }

        public Song()
        {
        }

        private string _Title = ""; public string Title { get => _Title; set { _Title = value; PropertyChanged(DBProperties.Title); } }
        private string _Author = ""; public string Author { get => _Author; set { _Author = value; PropertyChanged(DBProperties.Author); } }
        private string _Lyrics = ""; public string Lyrics { get => _Lyrics; set { _Lyrics = value; PropertyChanged(DBProperties.Lyrics); Set_Lyrics_Block(); } }
        private bool _IsFavorite = false; public bool IsFavorite { get => _IsFavorite; set { _IsFavorite = value; PropertyChanged(DBProperties.IsFavorite); } }

        public void Set_Lyrics_Block()
        {
            string MaxWidth = ""; Max_Lyrics_Block = new Lyrics_Block();
            Lyrics_Blocks = new List<Lyrics_Block>();
            List<string> List = new List<string>(_Lyrics.Split(new string[] { "\r\n" }, StringSplitOptions.None));
            Lyrics_Block LB = new Lyrics_Block();
            foreach (string Line in List)
            {
                if (Line.Length > MaxWidth.Length) MaxWidth = Line;
                bool ForceContinue = false;
                foreach (Header Header in MainLogic.HeaderList.Values)
                {
                    string HeadLow = Header.Title.ToLower();
                    string LinLow = Line.ToLower();
                    if (LinLow.IndexOf(HeadLow) == 0)
                    {
                        if (LB.Header != null) { Lyrics_Blocks.Add(LB); LB = new Lyrics_Block(); }
                        LB.Header = Header;
                        LB.HeaderFGBrush = Header.ForeGround_Brush;// The issue is here
                        LB.HeaderBGBrush = Header.BackGround_Brush;// The issue is here
                        LB.HeaderLine = Line;
                        LB.Set_Header_Icon();
                        ForceContinue = true;
                    }
                }
                if (ForceContinue) continue;
                if (Line == "") { Lyrics_Blocks.Add(LB); LB = new Lyrics_Block(); }
                else
                {
                    LB.Block_OneLine += Line + " ";
                    LB.Block += Line + Environment.NewLine;
                    LB.LineCount++;
                }
            }
            Max_Lyrics_Block.LineCount = Lyrics_Blocks.Select(xc => xc.LineCount).ToList().Max();
            for (int x = 0; x < Max_Lyrics_Block.LineCount; x++)
                Max_Lyrics_Block.Block += MaxWidth + Environment.NewLine;
        }

        public List<Lyrics_Block> Lyrics_Blocks = new List<Lyrics_Block>();
        public Lyrics_Block Max_Lyrics_Block = new Lyrics_Block();
    }

    public partial class Lyrics_Block
    {
        public Lyrics_Block Identity { get { return this; } }
        private Header _Header { get; set; }

        public Header Header { get { return _Header; } set { _Header = value; } }

        public Brush HeaderFGBrush { get; set; } = Brushes.Red;//test
        public Brush HeaderBGBrush { get; set; } = Brushes.Red;//test

        public string HeaderLine { get; set; } = "";
        public string HeaderIcon { get; set; } = "";
        public string Block { get; set; } = "";
        public string Block_OneLine { get; set; } = "";

        public int LineCount = 0;

        public void Set_Header_Icon() => HeaderIcon = Header.Abbreviation + HeaderLine.Replace(Header.Title, "").Trim();
    }
}

Here is the code for header:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;

namespace PHOWjection_Software_3._0.ItemType
{
    public partial class Header : DataBaseItem
    {
        public Header Identity { get { return this; } }

        private string _Title = ""; public string Title { get => _Title; set { _Title = value; PropertyChanged(DBProperties.Title); } }
        private string _Abbreviation = ""; public string Abbreviation { get => _Abbreviation; set { _Abbreviation = value; PropertyChanged(DBProperties.Abbreviation); } }

        public Brush BackGround_Brush { get; private set; }

        private string _BackGround = AppColors.TransparentHex; public string BackGround

        {
            get => _BackGround; set
            {
                _BackGround = value;
                BackGround_Brush = BackGround.ToBrush();
                PropertyChanged(DBProperties.BackGround);
            }
        }

        public Brush ForeGround_Brush { get; private set; }

        private string _ForeGround = AppColors.TransparentHex; public string ForeGround

        {
            get => _ForeGround; set
            {
                _ForeGround = value;
                ForeGround_Brush = ForeGround.ToBrush();
                PropertyChanged(DBProperties.ForeGround);
            }
        }
    }
}

The error that keeps appearing is

System.Windows.Markup.XamlParseException: 'Must create DependencySource on same Thread as the DependencyObject.'
Inner Exception
ArgumentException: Must create DependencySource on same Thread as the DependencyObject.

My code isn't muti-threading yet, Why does this error appear?

Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,670 questions
0 comments No comments
{count} votes

5 answers

Sort by: Most helpful
  1. Peter Fleischer (former MVP) 19,231 Reputation points
    2020-03-26T06:55:21.623+00:00

    Hi, you use implicitly multi-threading. Following code simulate your error:

    using PHOWjection_Software_3._0.ItemType;
    using System.Threading.Tasks;
    using System.Windows.Controls;
    
    namespace PHOWjection_Software_3._0.CustomControls
    {
      public partial class LyricsDisplay : UserControl
      {
        public LyricsDisplay()
        {
          InitializeComponent();
          GetData();
        }
    
        public void Display(Song Song)
        {
          View.Items.Clear();
          foreach (Lyrics_Block LB in Song.Lyrics_Blocks)
          {
            View.Items.Add(LB);
          }
          //Song.Lyrics_Blocks.ForEach(x => View.Items.Add(x));
        }
    
    
        private async void GetData()
        {
          await Task.Factory.StartNew(() =>
          {
            var s = new Song();
            for (int i = 0; i < 5; i++) s.Lyrics_Blocks.Add(new Lyrics_Block() { HeaderLine = $"HeaderLine {i}", Block = $"Block {i}" });
            Display(s);
          });
        }
      }
    }
    

    You can use Dispatcher to reroute executing Display.

    using PHOWjection_Software_3._0.ItemType;
    using System.Threading.Tasks;
    using System.Windows.Controls;
    
    namespace PHOWjection_Software_3._0.CustomControls
    {
      public partial class LyricsDisplay : UserControl
      {
        public LyricsDisplay()
        {
          InitializeComponent();
          GetData();
        }
    
        public void Display(Song Song)
        {
          View.Items.Clear();
          foreach (Lyrics_Block LB in Song.Lyrics_Blocks)
          {
            View.Items.Add(LB);
          }
          //Song.Lyrics_Blocks.ForEach(x => View.Items.Add(x));
        }
    
    
        private async void GetData()
        {
          await Task.Factory.StartNew(() =>
          {
            var s = new Song();
            for (int i = 0; i < 5; i++) s.Lyrics_Blocks.Add(new Lyrics_Block() { HeaderLine = $"HeaderLine {i}", Block = $"Block {i}" });
            Dispatcher.Invoke(()=> Display(s));
          });
        }
      }
    }
    

  2. Notch_Over_Heaven 1 Reputation point
    2020-03-26T16:31:16.107+00:00

    anonymous user-3316
    I restructured the code to match your suggestion

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    using PHOWjection_Software_3._0.ItemType;
    
    namespace PHOWjection_Software_3._0.CustomControls
    {
        public partial class LyricsDisplay : UserControl
        {
            public LyricsDisplay()
            {
                InitializeComponent();
                GetData();
            }
    
            public void Display(Song Song)
            {
                //View.Items.Clear();
                //foreach (Lyrics_Block LB in Song.Lyrics_Blocks)
                //{
                //    View.Items.Add(LB);
                //}
                ////Song.Lyrics_Blocks.ForEach(x => View.Items.Add(x));
            }
    
            private async void GetData()
            {
                await Task.Factory.StartNew(() =>
                {
                    var s = new Song();
                    for (int i = 0; i < 5; i++) s.Lyrics_Blocks.Add(new Lyrics_Block() { HeaderLine = $"HeaderLine {i}", Block = $"Block {i}" });
                    Dispatcher.Invoke(() => _Display(s));
                });
            }
    
            public void _Display(Song Song)
            {
                View.Items.Clear();
                foreach (Lyrics_Block LB in Song.Lyrics_Blocks)
                {
                    View.Items.Add(LB);
                }
            }
        }
    }
    

    The Same error kept appearing;

    System.Windows.Markup.XamlParseException: 'Must create DependencySource on same Thread as the DependencyObject.'
    Inner Exception
    ArgumentException: Must create DependencySource on same Thread as the DependencyObject.
    

  3. Peter Fleischer (former MVP) 19,231 Reputation points
    2020-03-26T17:04:47.177+00:00

    Hi, try this demo. Demo work without problems.

    XAML

    <Window x:Class="WpfApp2.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:WpfApp2"
            xmlns:uc="clr-namespace:PHOWjection_Software_3._0.CustomControls"
            mc:Ignorable="d"
            Title="MainWindow" Height="450" Width="800">
      <Grid>
        <uc:LyricsDisplay/>
      </Grid>
    </Window>
    
    <UserControl x:Class="PHOWjection_Software_3._0.CustomControls.LyricsDisplay"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                 xmlns:local="clr-namespace:PHOWjection_Software_3._0.CustomControls"
                 mc:Ignorable="d" 
                 d:DesignHeight="450" d:DesignWidth="800">
      <Grid>
        <ListBox x:Name="View" >
          <ListBox.ItemTemplate>
            <DataTemplate>
              <Border BorderBrush="Red" BorderThickness="2" Margin="2">
                <Grid>
                  <Grid.RowDefinitions>
                    <RowDefinition/>
                    <RowDefinition/>
                  </Grid.RowDefinitions>
                  <Grid.ColumnDefinitions>
                    <ColumnDefinition/>
                    <ColumnDefinition/>
                  </Grid.ColumnDefinitions>
                  <Label Grid.Row="0" Grid.Column="0" Content="HeaderLine"/>
                  <TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding HeaderLine}"/>
                  <Label Grid.Row="1" Grid.Column="0" Content="Block"/>
                  <TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Block}"/>
                </Grid>
              </Border>
            </DataTemplate>
          </ListBox.ItemTemplate>
        </ListBox>
      </Grid>
    </UserControl>
    

    Code:

    using PHOWjection_Software_3._0.ItemType;
    using System.Threading.Tasks;
    using System.Windows.Controls;
    
    namespace PHOWjection_Software_3._0.CustomControls
    {
      public partial class LyricsDisplay : UserControl
      {
        public LyricsDisplay()
        {
          InitializeComponent();
          GetData();
        }
    
        public void Display(Song Song)
        {
          View.Items.Clear();
          foreach (Lyrics_Block LB in Song.Lyrics_Blocks)
          {
            View.Items.Add(LB);
          }
          //Song.Lyrics_Blocks.ForEach(x => View.Items.Add(x));
        }
    
    
        private async void GetData()
        {
          await Task.Factory.StartNew(() =>
          {
            var s = new Song();
            for (int i = 0; i < 5; i++) s.Lyrics_Blocks.Add(new Lyrics_Block() { HeaderLine = $"HeaderLine {i}", Block = $"Block {i}" });
            Dispatcher.Invoke(()=> Display(s));
          });
        }
      }
    }
    
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Runtime.CompilerServices;
    using System.Windows.Media;
    
    namespace PHOWjection_Software_3._0.ItemType
    {
      public partial class Song : DataBaseItem
      {
        public Song Identity { get { return this; } }
        private string _Title = ""; public string Title { get => _Title; set { _Title = value; OnPropertyChanged(DBProperties.Title); } }
        private string _Author = ""; public string Author { get => _Author; set { _Author = value; OnPropertyChanged(DBProperties.Author); } }
        private string _Lyrics = ""; public string Lyrics { get => _Lyrics; set { _Lyrics = value; OnPropertyChanged(DBProperties.Lyrics); } }
        private bool _IsFavorite = false; public bool IsFavorite { get => _IsFavorite; set { _IsFavorite = value; OnPropertyChanged(DBProperties.IsFavorite); } }
        public List<Lyrics_Block> Lyrics_Blocks = new List<Lyrics_Block>();
        public Lyrics_Block Max_Lyrics_Block = new Lyrics_Block();
      }
    
      public partial class Lyrics_Block
      {
        public Lyrics_Block Identity { get { return this; } }
        private Header _Header { get; set; }
        public Header Header { get { return _Header; } set { _Header = value; } }
        public Brush HeaderFGBrush { get; set; } = AppColors.Red; //test
        public Brush HeaderBGBrush { get; set; } = AppColors.Red; //test
        public string HeaderLine { get; set; } = "";
        public string HeaderIcon { get; set; } = "";
        public string Block { get; set; } = "";
        public string Block_OneLine { get; set; } = "";
        public int LineCount = 0;
        public void Set_Header_Icon() => HeaderIcon = Header.Abbreviation + HeaderLine.Replace(Header.Title, "").Trim();
      }
    
      public class DataBaseItem : INotifyPropertyChanged
      {
        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged([CallerMemberName] string propeName = "") =>
          PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propeName));
      }
    
      public class Header
      {
        public string Abbreviation { get; set; }
        public string Title { get; set; }
      }
    
      public static class DBProperties
      {
        public static string Title { get; set; } = "Title";
        public static string Author { get; set; } = "Author";
        public static string Lyrics { get; set; } = "Lyrics";
        public static string IsFavorite { get; set; } = "IsFavorite";
      }
    
      public static class AppColors
      {
        public static Brush Red { get; set; } = Brushes.Red;
      }
    }
    

  4. Notch_Over_Heaven 1 Reputation point
    2020-03-26T21:18:58.623+00:00

    I forgot, there was a second thread

        public static partial class DataBase
        {
            public static Table SongBank = new Table { Name = "SongBank", Fields = new List<string> { "Title", "Author", "Lyrics", "IsFavorite" }, };
            public static Table HeaderBank = new Table { Name = "HeaderBank", Fields = new List<string> { "Title", "Abbreviation", "ForeGround", "BackGround" }, };
    
            public static void StartUp()
            {
                Thread Thread = new Thread(StartUpHandler);
                Thread.IsBackground = true;
                Thread.Start();
            }
    
            public static void StartUpHandler()
            {
                CreateConn();
                if (!ConnectionFailed)
                {
                    HeaderBank.Extract<Header>();
                    SongBank.Extract<Song>();
                    Panels.SongBank.CanUpdate = true;
                    MainLogic.Update_SongBank();
                }
                Thread.CurrentThread.Abort();
            }
    
            public static OdbcConnection MainConnection = new OdbcConnection();
            public static OdbcDataAdapter Reader;
            public static bool ConnectionFailed = false;
    
            public static void CreateConn()
            {
                string connetionString = "Driver={Microsoft Access Driver (*.mdb)};DBQ=SongBank.mdb;";
                MainConnection = new OdbcConnection(connetionString);
                try { MainConnection.Open(); MainConnection.Close(); ConnectionFailed = false; } catch { ConnectionFailed = true; }
            }
    
            public static void Extract<T>(this Table Table) where T : DataBaseItem, new()
            {
                DataTable TempData = new DataTable();
                Reader = new OdbcDataAdapter(Table.Select(), MainConnection);
                Reader.Fill(TempData);
    
                foreach (DataRow row in TempData.Rows)
                {
                    T DBItm = new T();
                    DBItm.SetID(row["ID"].ToString().ToInt32());
                    Table.Fields.ForEach(x => DBItm.SetValue(x, row[x]));
                    DBItm.BackUp();
                }
            }
    
            public static void Delete(Song Song) => SongBank.Delete(Song.ID);
        }
    

    The StartUp Method is call from the main window

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    using PHOWjection_Software_3._0.Windows;
    
    namespace PHOWjection_Software_3._0
    {
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
                this.AddAsParent();
                DataBase.StartUp();
                MainLogic.SongBank = MainSongBank;
                MainLogic.ScriptureBank = MainScriptureBank;
                MainLogic.MediaBank = MainMediaBank;
                MainLogic.LyricsDisplay_Pre = LyricsDisplay_Pre;
                MainLogic.LyricsDisplay_Live = LyricsDisplay_Live;
                Adjust_Header.Click += Adjust_Header_Click;
            }
    
            private void Adjust_Header_Click(object sender, RoutedEventArgs e) => (new HeaderManager()).Show();
        }
    }
    

  5. Peter Fleischer (former MVP) 19,231 Reputation points
    2020-03-27T04:08:31.73+00:00

    Hi, I recommend that you redesign your application. Now objects that use the user interface you instantiate in a separate thread. This can lead to errors. All objects that used in the user interface should be instantiated in the main thread (UI thread). If the content of these objects is to be changed from another thread, these accesses must be thread-safe. For this, e.g. a separate AsyncCollection can be used in which these accesses are redirected to the thread in which the collection was created (in the UI thread).

         public static partial class DataBase
         {
    /// 
             public static void StartUp()
             {
    ///
                 Thread.Start();
    
             public static void StartUpHandler()
             {
    ///
                     SongBank.Extract<Song>();
    ///
    
             public static void Extract<T>(this Table Table) where T : DataBaseItem, new()
             {
    /// 
                 foreach (DataRow row in TempData.Rows)
                 {
                     T DBItm = new T();
    ///
    
    0 comments No comments