Nie działa odświeżanie kontrolki ListView XAML z kodu C# wykonującego obliczenia w pętli

0

Mam aplikację WPF, w której procedura C# w pętli wykonuje obliczenia, które trochę trwają. Chciałbym wyniki obliczeń każdej pętli wyświetlać w** ListView (XAML), ale kontrolka nie chce się odświeżać. Wszystkie wyniki pojawiają się po wyjściu z procedury. Gdy na próbę w pętli umieściłem MessageBox.Show(‘’xx’’), to ListView** jest uzupełniany (odświeżany). Jak z tego wybrnąć? Proszę o pomoc.
Poniżej kod związany z moim problemem.
kontrolka XAML:

    <ListView x:Name="Podgląd"   FontFamily="Arial" FontSize="16"  HorizontalContentAlignment="Center" ScrollViewer.VerticalScrollBarVisibility="Auto"  BorderBrush="Black" BorderThickness="2" Background="LightYellow"  Margin="97,232,41,90" >
   <ListView.View >
     <GridView AllowsColumnReorder="False"  >
       <GridView.ColumnHeaderContainerStyle>
         <Style TargetType="GridViewColumnHeader">
           <Setter Property="FontSize" Value="20"/>
           <Setter Property="Foreground" Value="Blue"/>
           <Setter Property="HorizontalContentAlignment" Value="Left"/>
         </Style>
       </GridView.ColumnHeaderContainerStyle>
       <GridViewColumn Header="Celownik" Width="150"  DisplayMemberBinding="{Binding Path=Cel }"/>
          <GridViewColumn Header="Don" Width="150" DisplayMemberBinding="{Binding Path=Don}" />
          <GridViewColumn Header="Ic" Width="150" DisplayMemberBinding="{Binding Path=Ic}" />
          <GridViewColumn Header="kZb" Width="150" DisplayMemberBinding="{Binding Path=kZb}" />
          <GridViewColumn Header="exp" Width="150" DisplayMemberBinding="{Binding Path=exp}" />
        </GridView>
      </ListView.View>
    </ListView>

C#

  public class ZmianaWłaściwościPowiadomienie : INotifyPropertyChanged
  {
    #region INotifyPropertyChanged
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
      {
        if (PropertyChanged != null)
          PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
      }
      #endregion INotifyPropertyChanged
  }


  public class Item : ZmianaWłaściwościPowiadomienie
  {
    private string cel, don, wsp_kształtu, kzb, wykładnik;
    public string Cel
    {
      get
      {
        if (!String.IsNullOrEmpty(cel))
        {
          return cel;
        }
        else
        {
          return "";
        }
      }
      set
      {
        cel = value;
      OnPropertyChanged();
      }
    }
    public string Don
    {
      get
      {
        if (!String.IsNullOrEmpty(don))
        {
          return don;
        }
        else
        {
          return "";
        }
      }
      set
      {
        don = value;
        OnPropertyChanged();
      }
    }

// Pozostałe właściwości Item
}


  public class Kolekcja : INotifyCollectionChanged, IEnumerable
  {
    private List<Item> _lstItems = new List<Item>();

    public void Add(Item item)
    {
      _lstItems.Add(item);
      OnNotifyCollectionChanged(new NotifyCollectionChangedEventArgs(
          NotifyCollectionChangedAction.Add, item));
    }

    public void Remove(Item item)
    {
      _lstItems.Remove(item);
      OnNotifyCollectionChanged(new NotifyCollectionChangedEventArgs(
          NotifyCollectionChangedAction.Remove, item));
    }

    public void Clear()
    {
      _lstItems.Clear();
      OnNotifyCollectionChanged(new NotifyCollectionChangedEventArgs(
          NotifyCollectionChangedAction.Reset,null));
    }

    public Item this[Int32 index]
    {
      get
      {
        return this._lstItems[index];
      }
    }

    #region INotifyCollectionChanged
    private void OnNotifyCollectionChanged(NotifyCollectionChangedEventArgs args)
    {
      if (this.CollectionChanged != null)
      {
        this.CollectionChanged(this, args);

      }
    }
    public event NotifyCollectionChangedEventHandler CollectionChanged;
    #endregion INotifyCollectionChanged

    #region IEnumerable
    public List<Item>.Enumerator GetEnumerator()
    {
      return this._lstItems.GetEnumerator();
    }
    IEnumerator IEnumerable.GetEnumerator()
    {
      return (IEnumerator)this.GetEnumerator();
    }
    #endregion IEnumerable
  }

Kod główny programu:

  public partial class MainWindow : Window
  {
    Kolekcja kolekcja = new Kolekcja();
    public MainWindow()
    {
      InitializeComponent();
      Podgląd.ItemsSource = kolekcja;
//   Pozostałość
    }

//   Pozostałość
// Tu jest procedura licząca w pętli i wyświetlająca wyniki
    }

W pętli obliczającej stosuję:

 kolekcja.Add(new Item(Cel, Don, Ic, kZb, exp));

Pomocy!!!!!

W** WinForms **problem rozwiązywała następująca sekwencja:

List.Add(item);									
Application.DoEvents();

0

Spróbuj następująco:

Podgląd.DataContext= kolekcja;

A w XAML:

<ListView ItemsSource={binding} />
0

Dziękuję.
Sprubuję

0

Witam

Następujące zmiany:

Podgląd.DataContext= kolekcja;

A w XAML:

<ListView ItemsSource={binding} />

nic nie dały. Jest tak, jak przed zmianami.

1

Witam,

Może źródłem danych powinno być observable collection i musisz jakoś uporać się z aktualizacją tego z innego wątku (zapoznaj się z Dispatcher-em)

Pozdrawiam,

mr-owl

P.S. Albo zobacz jak działa praca na komunikatack (EventAgregator) w Prims.

0

Witam
Dzięki za podpowiedź.
Źródłem danych jest oservable collection. Próbuję poznać możliwości Dispatcher'a.

1

Z mojego programu (Viewmodel):

private IList<AnotherUserListElement> anotherUsersList = new ObservableCollection<AnotherUserListElement>();
        /// <summary>
        /// Lista wczytanych użytkowników
        /// </summary>
        public IList<AnotherUserListElement> AnotherUsersList
        {
            get
            {
                return anotherUsersList;
            }
            private set
            {
                anotherUsersList = value;
                OnPropertyChanged("AnotherUsersList");
            }
        }
        /// <summary>
        /// Dodaje element do Listy
        /// </summary>
        /// <param name="El">Nowy element</param>
        public void AddElement(AnotherUserListElement El)
        {
            AnotherUsersList.Add(El);
        }
        /// <summary>
        /// Usuwa element z listy
        /// </summary>
        /// <param name="El">Usuwany element</param>
        public void EraseElement(AnotherUserListElement El)
        {
            AnotherUsersList.Remove(El);
        }

Event, gdy Trzeba dodać element (viewmodel):

public event EventHandler<ResultInfo> NextElementCreated;

Obsługa eventu w modelu xaml.cs:

private void UserDataList_NextElementCreated(object sender, ResultInfo e)
        {
            switch (e.Result)
            {
                case eResult.Failed:
                    break;
                case eResult.Success:
                    Dispatcher.Invoke(() => Model.StepUserFoundList.UserDataList.AddElement(e.Data as AnotherUserListElement));
                    break;
            }
        }
1

Witam,

Ale jesteś pewien że do widoku przekazujesz ObservableCollection?

public IList<AnotherUserListElement> AnotherUsersList

Zobacz jak to wygląda w moim przykładowym programie

Pozdrawiam,

mr-owl

0

mr-owi nie dołączyłeś przykładu, o którym wspominasz. Przyślij proszę.
Pozdrawiam

0

Witam,

Zobacz pod https://github.com/gajda-ltd/FourProgrammersDotNet

Pozdrawiam,

mr-owl

0

Witam
Przepraszam, nie załapałem, że to jest ten sam program, który mi poleciłeś wcześniej. Dzięki.
Pozdrawiam

0

Witam
Dziękuję wszystkim za pomoc dzięki której udało się rozwiązać problem.
Jeszcze raz dziękuję i pozdrawiam

0

Witam,

To może zdradź jak go rozwiązałeś?

Pozdrawiam,

mr-owl

0

Witam
Jak wcześniej wspomniałem obliczenia wykonuje w pętli procedura wywoływana przyciskiem. Problem polegał na tym, że w czasie działania tej procedury nie miałem dostępu do okna celem wyświetlania wyników i zmiany właściwości kontrolek.
Rozwiązałem to tak:


namespace WspółczynnikKształtu
{
  public partial class MainWindow : Window
  {

    BackgroundWorker bg = new BackgroundWorker();
    Kolekcja kolekcja = new Kolekcja();
//inne deklaracje
    public MainWindow()

    {
      InitializeComponent();
      DataContext = kolekcja;
      labelTrybPracy.Visibility = Visibility.Hidden;
    }

//Pozostałe metody
}
}

namespace WspółczynnikKształtu
{
  public class Kolekcja : INotifyCollectionChanged, IEnumerable
  {
    private List<ElementKolekcji> _lstItems
      = new List<ElementKolekcji>();

    public void Add(ElementKolekcji item)
    {
      this._lstItems.Add(item);
      this.OnNotifyCollectionChanged(
        new NotifyCollectionChangedEventArgs(
          NotifyCollectionChangedAction.Add, item));
    }

    public void Remove(ElementKolekcji item)
    {
      this._lstItems.Remove(item);
      this.OnNotifyCollectionChanged(
        new NotifyCollectionChangedEventArgs(
          NotifyCollectionChangedAction.Remove, item));
    }

    public void Clear()
    {
      this._lstItems.Clear();
      this.OnNotifyCollectionChanged(
        new NotifyCollectionChangedEventArgs(
          NotifyCollectionChangedAction.Reset,null));
    }




    public ElementKolekcji this[Int32 index]
    {
      get
      {
        return this._lstItems[index];
      }
    }

    #region INotifyCollectionChanged
    private void OnNotifyCollectionChanged(NotifyCollectionChangedEventArgs args)
    {
      if (this.CollectionChanged != null)
      {
          this.CollectionChanged(this, args);
      }
    }
    public event NotifyCollectionChangedEventHandler CollectionChanged;
    #endregion INotifyCollectionChanged

    #region IEnumerable
    public List<ElementKolekcji>.Enumerator GetEnumerator()
    {
      return this._lstItems.GetEnumerator();
    }
    IEnumerator IEnumerable.GetEnumerator()
    {
      return (IEnumerator)this.GetEnumerator();
    }
    #endregion IEnumerable
  }
}

namespace WspółczynnikKształtu
{
  public class ElementKolekcji : ZmianaWłaściwościPowiadomienie
  {
    private string cel, don, wsp_kształtu, kzb, wykładnik;
    public string Cel
    {
      get
      {
        if (!String.IsNullOrEmpty(celownik))
        {
          return cel;
        }
        else
        {
          return "";
        }
      }
      set
      {
        celownik = value;
        OnPropertyChanged();
      }
    }
//itd
}


namespace WspółczynnikKształtu
{
  public class ZmianaWłaściwościPowiadomienie : INotifyPropertyChanged
  {
    #region INotifyPropertyChanged
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
      {
        if (PropertyChanged != null)
          PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
      }
      #endregion INotifyPropertyChanged
  }
}

W procedurze obsługującej naciśnięcie "buttona":

    private void Wykonaj_Clicked(object sender, RoutedEventArgs e)
    {
      bg.DoWork +=Bg_DoWork;
      if (!bg.IsBusy)
      {
        bg.RunWorkerAsync();
      }
    }


    private void Bg_DoWork(object sender, DoWorkEventArgs e)
    {
//To jest ta moja procedura
      Konwertuj();
    }


   private void Konwertuj()
    {
//Przykładowe zmiany w oknie
      this.Dispatcher.Invoke(() =>
      {
          this.labelTrybPracy.Visibility = Visibility.Hidden;
      });
      this.Dispatcher.Invoke(() =>
      {
        kolekcja.Clear();
      });
  
     this.Dispatcher.Invoke(() =>
    {
      this.labelTrybPracy.Content = "CZEKAJ! TERAZ INTENSYWNIE PRACUJĘ";
      this.labelTrybPracy.Foreground = Brushes.Red;
      this.labelTrybPracy.Visibility = Visibility.Visible;
     this.Wykonaj.IsEnabled = false;
     this.Koniec.IsEnabled = false;
 });


  this.Dispatcher.Invoke(() =>
 {
   ElementKolekcji element = new ElementKolekcji(SCelownik, SDonośność, SIc, SkZb, Sexp);
   kolekcja.Add(element);
  Podgląd.ScrollIntoView(element);
});


Tak to zrobiłem
Pozdrawiam

1

Witam,

Chyba trochę namieszałeś w tym kodzie, może rozrysuj sobie przepływ danych pomiędzy widokiem, viewmodel i swoim konwerterem. Przyjrzyj się jak to zostało zrealizowane w moim projekcie.

Pozdrawiam,

mr-owl

0

Klasa ** Kolekcja ** jest zbędna. Możesz użyć ObservableCollection<T>

0

Witam
Masz rację. Wystarczy:

    ObservableCollection<ElementKolekcji> kolekcja=new ObservableCollection<ElementKolekcji>();

Dzięki. Pozdrawiam.

1 użytkowników online, w tym zalogowanych: 0, gości: 1