0

I'm trying to create grid with static and dynamic columns. Dynamic columns should be under ColumnGroups. When I'm not using ColumnGroups everything works ok. But when I try to assign dynamic column to one of groups I get

The calling thread cannot access this object because a different thread owns it.

I create new window in separate thread

Thread newWindowThread=new Thread(new ThreadStart(() =>
        {
            var instrumentWindow=new InstrumentWindow();
            ((InstrumentWindowViewModel)instrumentWindow.DataContext).Initialize(instrument.ToString(),DateTime.Today);
            instrumentWindow.Show();
            System.Windows.Threading.Dispatcher.Run();
        }));

        newWindowThread.SetApartmentState(ApartmentState.STA);
        newWindowThread.IsBackground = true;

        newWindowThread.Start();

After I create static columns

this.EventGrid.Columns.Add(new GridViewDataColumn()
        {
            Header = "Time",
            DataMemberBinding = new Binding("Time"),
            DataType = typeof(DateTime)
        });

And actually function which is responsible for creating dynamic columns

Basically the idea is to create ColumnGroup for each term and under that group display term properties.

    private void InitDynamicColumns()
    {
        var maxTermCount = ((InstrumentWindowViewModel)this.DataContext).Events.Max(x => x.Terms.Length);
        var termHeaders = new List<string>();

        for (int i = 0; i < maxTermCount; i++)
        {
            var currentTerm = ((InstrumentWindowViewModel)this.DataContext).Events.First().Terms[i];
            var analyzerAmountType = currentTerm.Type == AnalyzerAmountType.Seconds ? "sec" : "ticks";
            this.EventGrid.ColumnGroups.Add(new GridViewColumnGroup
            {
                Header = currentTerm.Size + " " + analyzerAmountType + " term",
                Name = currentTerm.Size + analyzerAmountType + "term"
            });

            termHeaders.Add(currentTerm.Size + analyzerAmountType + "term");
        }

        for (int i = 0; i < maxTermCount; i++)
        {
            this.EventGrid.Columns.Add(new GridViewDataColumn()
            {
                Header = "Property1",
                DataMemberBinding = new Binding("Terms[" + i + "].Property1"),
                 ColumnGroupName = termHeaders[i]
            });
            this.EventGrid.Columns.Add(new GridViewDataColumn()
            {
                Header = "Property2",
                DataMemberBinding = new Binding("Terms[" + i + "].Property2"),
                  ColumnGroupName = termHeaders[i]
            });
            this.EventGrid.Columns.Add(new GridViewDataColumn()
            {
                Header = "Property3",
                DataMemberBinding = new Binding("Terms[" + i + "].Property3"),
                 ColumnGroupName = termHeaders[i]
            });
        }

    }

When I don't use ColumnGroups everything works as expected.But when I try to assig ColumnGroup to Column I get this Thread exception.

Thanks for any help.

1 Answers1

1

You can't create the window on one thread and the columns on another one if you indend to display the columns in a control within that window.

Just forget about this because it doesn't work because of the thread affinity:

Why do UI Controls in WPF have Thread Affinity?

You must create the window on the same thread as the one on which you create the columns and this is typically the main (UI) thread.

A WPF control may only be accessed on the thread on which it was originally created.

Community
  • 1
  • 1
mm8
  • 163,881
  • 10
  • 57
  • 88
  • Don't think it is the reason.As I do all manipulation with control in ModalWindow code behind. And for dynamic columns everything works perfect.It starts failing when I try to create and assign ColumnGroup. And this is strange – Volodymyr Babak Mar 31 '17 at 14:41
  • Don't Think what is the reason? Why are you creating a window on a background thread in the first place? Obviously you won't get any cross-threading errors if you create all controls on the same thread. – mm8 Mar 31 '17 at 14:42
  • I need to create several independent windows from main window. And each window will be getting independent data not blocking main window – Volodymyr Babak Mar 31 '17 at 14:50
  • Again: You *cannot* create a UI object on one thread and then use it in a control that was created on another thread. Just because you "don't think it is the reason" this doesn't change I am afraid. – mm8 Mar 31 '17 at 14:51
  • In that case why it works fine for dynamic columns?and fails for groups? Maybe you have any suggestions?not only criticising?) – Volodymyr Babak Mar 31 '17 at 14:55
  • I am not criticising, I am telling you why you are getting the exception. It is because you create a UI object on one thread and then try to access it on another one. – mm8 Mar 31 '17 at 14:58
  • Sorry.I pretty new on this site.I voted on your reply and marked it as answer. Can you suggest how to better solve this problem? I understand that I create Modal from Main window.But I don't know how to solve this situation another way.I still need those independant windows. – Volodymyr Babak Mar 31 '17 at 15:20
  • I am afraid there is no way to create an interactive element on one thread and then use it another thread. I am not sure whay you are actually trying to do here and what is "blocking" the main window. You should perform any long-running code on a *background* thread but this shouldn't involve any UI controls. They are always created on the UI thread. – mm8 Mar 31 '17 at 15:28
  • I'm trying create new STA thread where Modal window will be running.It has it's ViewModel which loads data for this window. Because when I create Window not in new thread it disables Main window and it shouldn't. – Volodymyr Babak Mar 31 '17 at 15:36
  • 1
    Nevermind.I found a solution.I didn't need another thread at all. Whole that "blocking" thing why I created new thread is fixed by using Show() instead ShowDialog() methods :) Thank you again for trying to help) – Volodymyr Babak Mar 31 '17 at 15:48