2013-01-10 16 views
5

Próbuję utworzyć bazę danych właściwości wartości paska postępu w WPF. Mam przycisk skonfigurowany do zwiększania właściwości int właściwości databound dla wartości ProgressBar. Kiedy wciskam przycisk, wartość ProgressBar powinna się policzyć w zakresie od 1 do 100. Jednak ... wydaje się, że nie działa i nie jestem pewien, co robię źle. Tu jest mój XAML ...Wtyczka WPF ProgressBar z wartością danych

<Window x:Class="ProgressBarExample2.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="MainWindow" Height="250" Width="400" Background="WhiteSmoke"> 
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center"> 
    <Button Name="goButton" Height="30" Width="50" Margin="0,10,0,50" Click="goButton_Click">GO!</Button> 
    <ProgressBar Name="progressBar" Width="300" Height="30" Value="{Binding Percent, UpdateSourceTrigger=PropertyChanged}" /> 
</StackPanel> 

i tu jest mój kod za ...

public partial class MainWindow : Window, INotifyPropertyChanged 
{ 
    #region INotifyPropertyChanged 

    public event PropertyChangedEventHandler PropertyChanged; 
    protected void NotifyPropertyChange(string propertyName) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 

    #endregion 

    private int percent = 0; 
    public int Percent 
    { 
     get { return this.percent; } 
     set 
     { 
      this.percent = value; 
      NotifyPropertyChange("Percent"); 
     } 
    } 

    public MainWindow() 
    { 
     InitializeComponent(); 
    } 


    private void goButton_Click(object sender, RoutedEventArgs e) 
    { 
     for (Percent = 0; Percent <= 100; Percent++) 
     { 
      Thread.Sleep(50); 
     } 
    } 
} 
+0

można chyba spróbować dodanie TIMER przycisk kliknij uruchomić stoper. W oddzwanianiu licznika zwiększa się procent - przy odpowiednim powiązaniu danych to powinno działać. Połączenia zwrotne są w wątku tła, więc twój główny wątek może zaktualizować pasek postępu. – Sarang

Odpowiedz

1

Nie ma kod (pisał), który ustawia DataContext okna (lub StackPanel).

Aby mieć pewność co do przyczyny, należy obejrzeć okno Wyjściowe błędy bindowania.


a ponadto

private void goButton_Click(object sender, RoutedEventArgs e) 
{ 
    for (Percent = 0; Percent <= 100; Percent++) 
    { 
     Thread.Sleep(50); 
    } 
} 

To blokuje przetwarzanie wiadomość więc aplikacja będzie „odpowiadać” przez 5 sekund. Bez przetwarzania wejściowego i bez aktualizacji ekranu. Zajęta pętla nie jest po prostu dobra w GUI sterowanym zdarzeniami.

Przenieś ten kod do środowiska pracy lub użyj zegara.

+0

Ahh, o czym zapomniałem ... OK, naprawiono to w pewnym sensie ... ale nie aktualizuje wartości w czasie rzeczywistym ... teraz po prostu przeskakuje od 0 do 100 procent, nawet jeśli wydłużam czas snu ... – user1451495

+0

Dodałem na to odpowiedź. –

6

Thread.Sleep blokuje wątek interfejsu użytkownika i zatrzymuje animację paska postępu.

Możesz użyć następujących opcji, aby wstrzymać wykonywanie bez blokowania wątku interfejsu użytkownika. Wymień połączenia Thread.Sleep(50) z Wait(50)

EDIT: Usunięto delegat

/// <summary> 
/// Stop execution for a specific amount of time without blocking the UI 
/// </summary> 
/// <param name="interval">The time to wait in milliseconds</param> 
public static void Wait(int interval) 
{ 
    ExecuteWait(() => Thread.Sleep(interval)); 
} 

public static void ExecuteWait(Action action) 
{ 
    var waitFrame = new DispatcherFrame(); 

    // Use callback to "pop" dispatcher frame 
    IAsyncResult op = action.BeginInvoke(dummy => waitFrame.Continue = false, null); 

    // this method will block here but window messages are pumped 
    Dispatcher.PushFrame(waitFrame); 

    // this method may throw if the action threw. caller's responsibility to handle. 
    action.EndInvoke(op); 
} 
+0

Zmarnował cały dzień, próbując dowiedzieć się, dlaczego interfejs użytkownika jest zamrożony. Nowicjusz mnie. – NotAgain

0

Istnieją inne rozwiązania bez wiązania z danymi. Można zadeklarować delegat

private delegate void UpdateProgressBarDelegate(System.Windows.DependencyProperty dp, Object value);

i użyć go w przypadku kliknięcia przycisku

private void goButton_Click(object sender, RoutedEventArgs e) 
     { 
      //Configure the ProgressBar 
      progressBar.Minimum = 0; 
      progressBar.Maximum = 100; 
      progressBar.Value = 0; 

      //Stores the value of the ProgressBar 
      double value = 0; 

      //Create a new instance of our ProgressBar Delegate that points 
      // to the ProgressBar's SetValue method. 
      UpdateProgressBarDelegate updatePbDelegate = new UpdateProgressBarDelegate(progressBar.SetValue); 

      //Tight Loop: Loop until the ProgressBar.Value reaches the max 
      do 
      { 
       value += 1; 

       /*Update the Value of the ProgressBar: 
        1) Pass the "updatePbDelegate" delegate that points to the ProgressBar1.SetValue method 
        2) Set the DispatcherPriority to "Background" 
        3) Pass an Object() Array containing the property to update (ProgressBar.ValueProperty) and the new value */ 
       Dispatcher.Invoke(updatePbDelegate, 
        System.Windows.Threading.DispatcherPriority.Background, 
        new object[] { ProgressBar.ValueProperty, value }); 

      } 
      while (progressBar.Value != progressBar.Maximum); 
     } 
Powiązane problemy