WPF mvvm фоновый рабочий интерфейс не обновлен

Я использую BusyIndicator в своей программе, цель которого - показать индикатор занятости в представлении, в то время как viewModel загружает данные из базы данных.

* Примечание: до того, как я добавил фоновый рабочий, все работало отлично.

Моя программа построена таким образом:

У меня есть представление, которое содержит:

<NetworkUI:NetworkView
                        x:Name="networkControl"

                        NodesSource="{Binding Network.Nodes}"
                        ConnectionsSource="{Binding Path=Network.Connections}"


                        MouseDown="networkControl_MouseDown"
                        MouseUp="networkControl_MouseUp"
                        MouseMove="networkControl_MouseMove"

                        />

Где Network.Nodes и Network.Connections - моя проблема (мне нужно их видеть, а я нет)

Они связаны с viewModel с именем mainWindowViewModel, основным методом получения данных из базы данных с именем ShowSystem:

public void ShowSystem(bool update)
    {



        List<String> interfacesForFlow = new List<String>();
              #region CreateNetworkClasses

        MethodInfo getInterfacesWithGuidToFlow = dbType.GetMethod("getInterfacesWithGuidToFlow");

        #endregion


        MainNet = Common.Model.Network.getNetwork();
        Debug.WriteLine("MainNet.Systems.Count = " + MainNet.Systems.Count);
        if (MainNet.Systems.Count == 0)
            update = true;
        List<String> systemNames = new List<string>();
        if (update)
        {
            if(MainNet.Systems.Count > 0)
                MainNet.Systems.Clear();
            if (this.Network.Nodes.Count > 0)
            {
                this.Network.Nodes.Clear();
                this.Network.Connections.Clear();
            }

            try
            {
                systemNames = (List<String>)getAllSystemMethod.Invoke(sqlDB, null);
                Debug.WriteLine("Success getAllSystemMethod");
            }
            catch (Exception ex)
            {
                logger.addMessage("Error in getAllSystemMethod: " + ex.Message + " Inner: " + ex.InnerException.Message);
                Debug.WriteLine("Error in getAllSystemMethod: " + ex.Message + " Inner: " + ex.InnerException.Message);
            }

            #region CreateSystems
            foreach (var sysName in systemNames)
            {
                #region Intializating
                ObservableCollection<Common.Model.Enum> enums = new ObservableCollection<Common.Model.Enum>();
                ObservableCollection<Common.Model.Struct> structs = new ObservableCollection<Common.Model.Struct>();
                ObservableCollection<Common.Model.Interface> interfaces = new ObservableCollection<Common.Model.Interface>();
                //List<Model.Enum> enums = new List<Model.Enum>();
                //List<Model.Struct> structs = new List<Model.Struct>();
                //List<Model.Interface> interfaces = new List<Model.Interface>();

                int systemId = -1;
                Object[] getSystemIdParams = new Object[1];
                getSystemIdParams[0] = sysName;
                try
                {
                    systemId = (int)getSystemId.Invoke(sqlDB, getSystemIdParams);
                    Debug.WriteLine("Success getSystemId systemId = " + systemId);
                }
                catch (Exception ex)
                {
                    logger.addMessage("Error in getSystemId: " + ex.Message + " Inner: " + ex.InnerException.Message);
                    Debug.WriteLine("Error in getSystemId: " + ex.Message + " Inner: " + ex.InnerException.Message);
                }

                List<int> sysEnumsIds = new List<int>();
                List<int> sysStructsIds = new List<int>();
                List<int> sysInterfacesIds = new List<int>();

                Object[] getSysEnumsIdParams = new Object[1];
                getSysEnumsIdParams[0] = systemId;
                try
                {
                    sysEnumsIds = (List<int>)getSysEnumsId.Invoke(sqlDB, getSysEnumsIdParams);      //return List<int> all system Enums ids
                    if (sysEnumsIds.Count > 0)
                        Debug.WriteLine("Success getSysEnumsId first count is " + sysEnumsIds.Count);
                    else
                        Debug.WriteLine("success getSysEnumsId but no ids found");
                }
                catch (Exception ex)
                {
                    logger.addMessage("Error in getSysEnumsId: " + ex.Message + " Inner: " + ex.InnerException.Message);
                    Debug.WriteLine("Error in getSysEnumsId: " + ex.Message + " Inner: " + ex.InnerException.Message);
                }


                Object[] getSysStructsIdParams = new Object[1];
                getSysStructsIdParams[0] = systemId;
                try
                {
                    sysStructsIds = (List<int>)getSysStructsId.Invoke(sqlDB, getSysStructsIdParams);
                    if (sysStructsIds.Count > 0)
                        Debug.WriteLine("success getSysStructsId count = " + sysStructsIds.Count);
                    else
                        Debug.WriteLine("success getSysStructsId but no ids found");
                }
                catch (Exception ex)
                {
                    logger.addMessage("Error in getSysStructsId: " + ex.Message + " Inner: " + ex.InnerException.Message);
                    Debug.WriteLine("Error in getSysStructsId: " + ex.Message + " Inner: " + ex.InnerException.Message);
                }


                Object[] getSysInterfacesIdParams = new Object[1];
                getSysInterfacesIdParams[0] = systemId;
                try
                {
                    sysInterfacesIds = (List<int>)getSysInterfacesId.Invoke(sqlDB, getSysInterfacesIdParams);
                    if (sysInterfacesIds.Count > 0)
                        Debug.WriteLine("Success getSysInterfacesId count = " + sysInterfacesIds.Count);
                    else
                        Debug.WriteLine("success getSysInterfacesId but no ids found");
                }
                catch (Exception ex)
                {
                    logger.addMessage("Error in getSysInterfacesId: " + ex.Message + " Inner: " + ex.InnerException.Message);
                    Debug.WriteLine("Error in getSysInterfacesId: " + ex.Message + " Inner: " + ex.InnerException.Message);
                }
                #endregion



                #region GetInterfaces
                foreach (var @interface in sysInterfacesIds)        //get interface
                {

                    ObservableCollection<Common.Model.Message> messages = new ObservableCollection<Common.Model.Message>();
                    ObservableCollection<Common.Model.Definition> definitions = new ObservableCollection<Common.Model.Definition>();
                    ObservableCollection<Common.Model.Include> includes = new ObservableCollection<Common.Model.Include>();

                    List<int> includesIds = new List<int>();
                    List<int> definitionsIds = new List<int>();
                    List<int> messagesIds = new List<int>();


                    #region getIncludes
                    Object[] getIncludesIdsParams = new object[1];
                    getIncludesIdsParams[0] = @interface;
                    try
                    {
                        includesIds = (List<int>)getIncludesIds.Invoke(sqlDB, getIncludesIdsParams);
                        Debug.WriteLine("Success getIncludesIds " + includesIds.Count);
                    }
                    catch (Exception ex)
                    {
                        logger.addMessage("Error in getIncludesIds: " + ex.Message + " Inner: " + ex.InnerException.Message);
                        Debug.WriteLine("Error in getIncludesIds: " + ex.Message + " Inner: " + ex.InnerException.Message);
                    }

                    foreach (var id in includesIds)
                    {
                        Object[] getIncludeParams = new object[1];
                        getIncludeParams[0] = id;
                        string includeName = "";
                        try
                        {
                            includeName = (string)getInclude.Invoke(sqlDB, getIncludeParams);
                            Debug.WriteLine("Success get include name = " + includeName);
                        }
                        catch (Exception ex)
                        {
                            logger.addMessage("Error in getInclude " + ex.Message + " Inner: " + ex.InnerException.Message);
                            Debug.WriteLine("Error in getInclude " + ex.Message + " Inner: " + ex.InnerException.Message);
                        }
                        includes.Add(new Common.Model.Include(includeName));
                    }
                    #endregion

                    #region getdefinitions
                    Object[] getdefinitionsIdsParams = new object[1];
                    getdefinitionsIdsParams[0] = @interface;
                    try
                    {
                        definitionsIds = (List<int>)getDefinitionsIds.Invoke(sqlDB, getdefinitionsIdsParams);
                        Debug.WriteLine("Success getDefinitionsIds " + definitionsIds.Count);
                    }
                    catch (Exception ex)
                    {
                        logger.addMessage("Error in getDefinitionsIds: " + ex.Message + " Inner: " + ex.InnerException.Message);
                        Debug.WriteLine("Error in getDefinitionsIds: " + ex.Message + " Inner: " + ex.InnerException.Message);
                    }

                    foreach (var id in definitionsIds)
                    {
                        List<Object> definition = new List<object>();

                        Object[] getDefinitionParams = new object[1];
                        getDefinitionParams[0] = id;
                        string includeName = "";
                        try
                        {
                            definition = (List<Object>)getDefinition.Invoke(sqlDB, getDefinitionParams);
                            Debug.WriteLine("Success getDefinisions " + definition[0]);
                        }
                        catch (Exception ex)
                        {
                            logger.addMessage("Error in getInclude " + ex.Message + " Inner: " + ex.InnerException.Message);
                            Debug.WriteLine("Error in getInclude " + ex.Message + " Inner: " + ex.InnerException.Message);
                        }

                        definitions.Add(new Common.Model.Definition(Convert.ToString(definition[0]), Convert.ToInt32(definition[1])));

                    }
                    #endregion


                    Object[] getInterfaceFromIdParam = new Object[1];
                    getInterfaceFromIdParam[0] = @interface;
                    List<Object> tempInterface = new List<object>();
                    try
                    {

                        tempInterface = (List<Object>)getInterfaceFromId.Invoke(sqlDB, getInterfaceFromIdParam);

                        Debug.WriteLine("Success getInterfaceFromId " + tempInterface.Count);
                    }
                    catch (Exception ex)
                    {
                        logger.addMessage("Error in getInterfaceFromId : " + ex.Message + " Inner: " + ex.InnerException.Message);
                        Debug.WriteLine("Error in getInterfaceFromId : " + ex.Message + " Inner: " + ex.InnerException.Message);
                    }
                    interfaces.Add(new Common.Model.Interface(messages, definitions, includes, Convert.ToString(tempInterface[0]), Convert.ToString(tempInterface[1]), Convert.ToInt32(tempInterface[2]), Convert.ToInt32(tempInterface[3]), Convert.ToBoolean(tempInterface[4])));
                    Debug.WriteLine("Success adding new interface: " + interfaces.Last().Name);

                }

                #endregion

                #region InputOutputNumber
                List<int> inputs = new List<int>();
                List<int> outputs = new List<int>();

                int inputCount = 0;
                int outputCount = 0;

                Object[] getSysInputNumParams = new Object[1];
                getSysInputNumParams[0] = systemId;
                try
                {
                    inputs = (List<int>)getSysInputs.Invoke(sqlDB, getSysInputNumParams);
                    if (inputs != null)
                    {
                        inputCount = inputs.Count;
                        Debug.WriteLine("Success getSysInputNum inputs = " + inputCount);
                    }
                    else
                        Debug.WriteLine("Success getSysInputNum inputs = 0");
                }
                catch (Exception ex)
                {
                    logger.addMessage("Error in getSysInputNum: " + ex.Message + " Inner: " + ex.InnerException.Message);
                    Debug.WriteLine("Error in getSysInputNum: " + ex.Message + " Inner: " + ex.InnerException.Message);
                }


                Object[] getSysOutputNumParams = new Object[1];
                getSysOutputNumParams[0] = systemId;
                try
                {
                    outputs = (List<int>)getSysOutputs.Invoke(sqlDB, getSysOutputNumParams);
                    if (outputs != null)
                    {
                        outputCount = outputs.Count;
                        Debug.WriteLine("Success getSysOutputNum outputs = " + outputCount);
                    }
                    else
                        Debug.WriteLine("Success getSysOutputNum outputs = 0");
                }
                catch (Exception ex)
                {
                    logger.addMessage("Error in getSysOutputNum: " + ex.Message + " Inner: " + ex.InnerException.Message);
                    Debug.WriteLine("Error in getSysOutputNum: " + ex.Message + " Inner: " + ex.InnerException.Message);
                }
                #endregion

                Common.Model.System system = null;
                try
                {
                    system = new Common.Model.System(interfaces, enums, structs, sysName, inputCount, outputCount, inputs, outputs);
                    Debug.WriteLine("Success adding new system");
                }
                catch (Exception ex)
                {
                    logger.addMessage("Error in creating new system: " + ex.Message);
                    Debug.WriteLine("Error in creating new system: " + ex.Message);
                }
                MainNet.Systems.Add(system);
                Debug.WriteLine("Done! you now have a new system with: " + interfaces.Count + " interfaces And " + enums.Count + " Enums and " + structs.Count + " Structs, The name is: " + sysName + " numOfInput: " + inputCount + " numOfOutput: " + outputCount);
            #endregion


            }
        #endregion
            }

            #region addNodesToUi

             //Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => ));

            try
            {
                //Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => ));

                Debug.WriteLine("Success creating new nodeViewModel");
            }
            catch (Exception ex)
            {
                logger.addMessage("Error in creating new nodeViewModel " + ex.Message + " Inner: " + ex.InnerException.Message);
                Debug.WriteLine("Error in creating new nodeViewModel " + ex.Message + " Inner: " + ex.InnerException.Message);
            }
            int width = 0;
            int height = 0;

            foreach (var system in MainNet.Systems)
            {
                Debug.WriteLine("inside Foreach in system: " + system.Name + " interface " + system.Interfaces.Count + " structs " + system.Structs.Count);
                if (nodes == null)
                    Debug.WriteLine("FUUUCCKKKK!");
                try
                {
                    Debug.WriteLine("Before add node");
                    try
                    {
                        Debug.WriteLine("trying to add: " + system.Name + " " + system.InputNum + " " + system.OutputNum + " " + system.Interfaces.Count + " " + system.Enums.Count + " " + system.Structs.Count);
                        Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => nodes.Add(CreateNode(system.Name, new Point(width, height), false, system.InputNum, system.OutputNum, system.Interfaces, system.Enums, system.Structs, update))));

                    }

                    catch (Exception ex)
                    {
                        logger.addMessage("Error adding new node to list " + ex.Message + " Inner: " + ex.InnerException.Message);
                        Debug.WriteLine("Error adding new node to list " + ex.Message + " Inner: " + ex.InnerException.Message);
                    }
                    Debug.WriteLine("Success adding new node to list");
                }
                catch (Exception ex)
                {
                    logger.addMessage("Error in adding new node to list " + ex.Message + " Inner: " + ex.InnerException.Message);
                    Debug.WriteLine("Error in adding new node to list " + ex.Message + " Inner: " + ex.InnerException.Message);
                }
                width += 150;
                if (width >= 700)
                {
                    width = 0;
                    height += 100;
                }
            }

            if (MainWindow.IsFlow)
            {
                Object[] getInterfacesWithGuidToFlowParam = new Object[1];
                getInterfacesWithGuidToFlowParam[0] = MainWindow.GuidToFlow;

                    try
                    {
                        interfacesForFlow = (List<String>)getInterfacesWithGuidToFlow.Invoke(sqlDB, getInterfacesWithGuidToFlowParam);

                        Debug.WriteLine("Success getInterfacesWithGuidToFlow " + interfacesForFlow.Count);
                    }
                    catch (Exception ex)
                    {
                        logger.addMessage("Error in getInterfacesWithGuidToFlow : " + ex.Message + " Inner: " + ex.InnerException.Message);
                        Debug.WriteLine("Error in getInterfacesWithGuidToFlow : " + ex.Message + " Inner: " + ex.InnerException.Message);
                    }

            }

            foreach (var system in MainNet.Systems)
            {
                if (system.OutputNum > 0)       //this system has an output connector
                {
                    int i = 0;
                    foreach (var outId in system.Outputs)       //loop throw all systems ids that current system is connected to 
                    {
                        Debug.WriteLine("out id = " + outId);
                        ConnectionViewModel connection = null;
                        try
                        {
                            Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => connection = new ConnectionViewModel()));

                            Debug.Write("Success creating new ConnectionViewModel");
                        }
                        catch (Exception ex)
                        {
                            logger.addMessage("Error in creating new ConnectionViewModel " + ex.Message + " Inner: " + ex.InnerException.Message);
                            Debug.WriteLine("Error in creating new ConnectionViewModel " + ex.Message + " Inner: " + ex.InnerException.Message);
                        }
                        Object[] getSystemNameParams = new Object[1];
                        getSystemNameParams[0] = outId;
                        string destSystemName = "";
                        try
                        {
                            destSystemName = (String)getSystemName.Invoke(sqlDB, getSystemNameParams);
                        }
                        catch (Exception ex)
                        {
                            logger.addMessage("Error in getSystemName: " + ex.Message + " Inner: " + ex.InnerException.Message);
                            Debug.WriteLine("Error in getSystemName: " + ex.Message + " Inner: " + ex.InnerException.Message);
                        }

                        NodeViewModel sourceItem = null;
                        NodeViewModel destItem = null;
                        Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => sourceItem = nodes.Find(x => x.Name == system.Name)));

                        //int sourceId = nodes.FindIndex(sourceItem);
                        Debug.Write("Success creating new sourceItem");
                        Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => destItem = nodes.Find(x => x.Name == destSystemName)));

                        Debug.Write("Success creating new destItem");
                        try
                        {
                            Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => destItem.InputSystems.Add(sourceItem.Name)));

                        }
                        catch (Exception ex)
                        {
                            logger.addMessage("Error adding input system: " + ex.Message);
                            Debug.Write("Error adding input system: " + ex.Message);
                        }
                        try
                        {
                            Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => sourceItem.OutputSystems.Add(destItem.Name)));

                        }
                        catch (Exception ex)
                        {
                            logger.addMessage("Error adding OutputSystems: " + ex.Message);
                            Debug.Write("Error adding OutputSystems: " + ex.Message);
                        }
                        Debug.Write("Success bah");
                        //int destId = nodes.FindIndex(destItem);


                        Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => connection.SourceConnector = sourceItem.OutputConnectors[i++]));

                        Debug.Write("Success bah");
                        Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => connection.DestConnector = destItem.InputConnectors[destItem.InputConnectors.Count - 1]));

                        Debug.Write("Success bah");

                        // Add the connection to the view-model.
                        //
                        Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => connection.Type = ConnectionViewModel.ConnectorType.REGULAR));
                        Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => this.Network.Connections.Add(connection)));


                        //Debug.Write("Success bah");
                        if (MainWindow.IsFlow)
                        {
                            Debug.WriteLine("inside IsFlow!");

                            foreach (var @interface in interfacesForFlow)
                            {
                                String[] systems = @interface.Split('_');
                                Debug.WriteLine("Flow from: " + systems[0] + " To " + systems[1]);
                                if(systems[0].Equals(sourceItem.Name) && systems[1].Equals(destItem.Name))
                                    Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => connection.Type = ConnectionViewModel.ConnectorType.FLOW));

                            }                                 

                        }
                    }
                }
            }
            #endregion

    }

И этот метод вызывается из метода backgroundWorker DoWork, все эти ссылки на backgroundWorker:

public MainWindowViewModel()
    {
        //
        // Create a network, the root of the view-model.
        //

        Network = new NetworkViewModel();
        nodes = new List<NodeViewModel>();
        //ShowSystem(false);
        bw = new BackgroundWorker();
        bw.DoWork += new DoWorkEventHandler(bw_DoWork);
        bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
        bw.RunWorkerAsync(false);



        //create networkt according to classes created
    }

    void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        //Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => this.IsBusy = false));
        this.IsBusy = false;
        Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => OnPropertyChanged("Network")));
    }

    void bw_DoWork(object sender, DoWorkEventArgs e)
    {

        //Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => ));
        this.BusyContent = "Please Wait...";
        this.IsBusy = true;
        Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => ShowSystem((bool)e.Argument)));
    }

3 ответа

Вы не реализовали свой BackgroundWorker правильно, несмотря на то, что я уже предоставил вам ссылку, чтобы увидеть, как это должно быть реализовано в комментариях:

Обновление Progress Bar от фонового рабочего срыва

Ты даже не звонишь своему ShowSystem метод из BackgroundWorkerИтак, как вы ожидаете получить какие-либо данные?

void bw_DoWork(object sender, DoWorkEventArgs e)
{
    //You should only update UI properties from here using Dispatcher.CurrentDispatcher
    this.BusyContent = "Please Wait...";
    this.IsBusy = true;
    Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => OnPropertyChanged("Network")));
    //This runs on the background thread so this is where you do long running process
    ShowSystem(false);
}

Вы явно не научились использовать BackgroundWorker тем не менее, это то, что вы должны делать, а не приходить сюда и задавать повторяющиеся вопросы. Я уже дал вам ссылку на один пример правильной реализации BackgroundWorker и вы можете найти другой на странице класса BackgroundWorker в MSDN.

Я верю, что этого будет достаточно, чтобы вы снова пошли.

Работает ли пользовательский интерфейс в потоке пользовательского интерфейса, используя диспетчер. Смотрите здесь для получения дополнительной информации. В общем, все, что имеет отношение к элементу управления UI, должно быть отправлено в поток UI.

Вы должны вызвать метод в главном потоке из doWork, который выполняется в отдельном потоке, чтобы обновить пользовательский интерфейс.

Я бы посоветовал взглянуть на http://msdn.microsoft.com/en-us/library/dd460693%28v=vs.110%29.aspx который доступен в.NET4 и выше. (Посмотрите на задание конкретно)

Другие вопросы по тегам