Binding WPF Progress Bar never updating - c#

During the OnPropertyChanged(), the PropertyChanged event is always NULL so the event never gets called. What am I missing?
Here is the XML Code:
<ProgressBar x:Name="ProgressBar1" Value="{Binding PBarValue, UpdateSourceTrigger=PropertyChanged}" Width="200" Height="20" Minimum="0" Maximum="100"></ProgressBar>
C# Code:
public PBar progress_bar = new PBar();
public class PBar : INotifyPropertyChanged
{
private int _progress;
public int progress
{
get { return _progress; }
set
{
if (value != _progress)
{
_progress = value;
OnPropertyChanged("PBarValue");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
}
private void Main_Initialized(object sender, EventArgs e)
{
ProgressBar1.DataContext = progress_bar;
progress_bar.progress=75; // This does call the set and
// OnPropertyChanged but
// PropertyChanged is always null
// so it never updates UI
}
I am setting the "value" of the Progress Bar from another thread so this is why I need the binding.
I have tried this so many different ways at this point my head is spinning!

Change your xaml to bind to progress:
<ProgressBar x:Name="ProgressBar1" Value="{Binding progress, UpdateSourceTrigger=PropertyChanged}" Width="200" Height="20" Minimum="0" Maximum="100"></ProgressBar>
And then change your property to raise notification on "progress" and not "PBarValue":
private int _progress;
public int progress
{
get { return _progress; }
set
{
if (value != _progress)
{
_progress = value;
OnPropertyChanged("progress");
}
}
}

Please change your binding in the XAML from PBarValue to progress. Refer below code.
<ProgressBar x:Name="ProgressBar1" Value="{Binding progress, UpdateSourceTrigger=PropertyChanged}" Width="200" Height="20" Minimum="0" Maximum="100"></ProgressBar>

Related

Calculated field not updating until edited in UI

I'm trying to test out data binding with XAML and C# as a novice programmer. I have two sliders that are bound to properties and I want to update a TextBox with the sum of the two values of the properties set by the sliders.
I'm using INotifyPropertyChanged and tried changing every property I could find but I can't get the textbox to update until I edit the textbox, at which point, the textbox updates to the correct value. Using UpdateSourceTrigger=PropertyChanged only updates the textbox as soon as I edit the textbox instead of when I select another element. I've tried writing a separate event handler that doesn't use [CallerNameMember] and uses a specified property but it didn't seem to change anything.
<Grid>
<Grid.RowDefinitions>
</Grid.RowDefinitions>
<TextBox Grid.Row="0"
Text="{Binding BoundNumber, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
FontSize="20"
FontWeight="Bold"
AllowDrop="False" />
<Slider Grid.Row="1"
Value="{Binding BoundNumber, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Maximum="100"
Minimum="10"
IsSnapToTickEnabled="True"
TickFrequency="10" />
<TextBox Grid.Row="2"
Text="{Binding BoundNumber2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
AllowDrop="False" />
<Slider Grid.Row="3"
Value="{Binding BoundNumber2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Maximum="100"
Minimum="10"
IsSnapToTickEnabled="True"
TickFrequency="10" />
<TextBox Grid.Row="4"
Name="MathBox"
Text="{Binding QuickMath, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True}">
</TextBox>
</Grid>
public partial class OrderScreen : INotifyPropertyChanged
{
public OrderScreen()
{
DataContext = this;
InitializeComponent();
}
private int quickMath;
public int QuickMath
{
get { return _boundNumber + _boundNumber2; }
set
{
if (value != quickMath)
{
quickMath = value;
OnPropertyChanged();
}
}
}
private int _boundNumber;
public int BoundNumber
{
get { return _boundNumber; }
set
{
if (_boundNumber != value)
{
_boundNumber = value;
// MathBox.Text = quickMath.ToString();
OnPropertyChanged();
}
}
}
private int _boundNumber2;
public int BoundNumber2
{
get { return _boundNumber2; }
set
{
if (_boundNumber2 != value)
{
_boundNumber2 = value;
MathBox.Text = quickMath.ToString();
OnPropertyChanged();
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
I can get it to work with the commented out MathBox.Text = quickMath.ToString(); but I was hoping there was a better way to do this with data binding. Thanks in anticipation!
Binding mechanism subscribes to the PropertyChanged event of DataSource object, so there is no need to "initialize" the event along with the INPC implementation, but as you might have noticed, PropertyChanged event for the QuickMath property is indeed never triggered when BoundNumber or BoundNumber2 are changed.
You can fix it in different ways, e.g. explicitly call OnPropertyChanged for all affected properties:
private int _boundNumber;
public int BoundNumber
{
get { return _boundNumber; }
set
{
if (_boundNumber != value)
{
_boundNumber = value;
OnPropertyChanged();
OnPropertyChanged(nameof(QuickMath));
}
}
}
Note that this way you can keep QuickMath property a read-only. This approach works nicely in other situations, like with time-related properties, say if your data source property formats a string like "Edited 2 minutes ago" based on a recorded timestamp and current time and you call PropertyChanged as a timed task.
public int QuickMath => _boundNumber + _boundNumber2;
Alternatively, you can update QuickMath along with modifying BoundNumber and BoundNumber2 to trigger OnPropertyChanged() call inside QuickMath setter:
private int _boundNumber2;
public int BoundNumber2
{
get { return _boundNumber2; }
set
{
if (_boundNumber2 != value)
{
_boundNumber2 = value;
OnPropertyChanged();
QuickMath = BoundNumber + BoundNumber2;
}
}
}
This makes sense if the logic in QuickMath wouldn't allow making it a read-only property. In this case you have to adjust the getter accordingly and use private or protected setter there to avoid data inconsistency and unexpected behavior.
private int _quickMath;
public int QuickMath
{
get { return _quickMath; }
private set
{
if (value != _quickMath)
{
_quickMath = value;
OnPropertyChanged();
}
}
}
In both cases there is no need for two-way binding to QuickMath:
<TextBlock Grid.Row="4" Text="{Binding QuickMath, Mode=OneWay}"/>
On a side-note and looking at the rest of the code, it really worth mentioning that binding mechanism is expected to segregate UI from the data, where XAML knows about data source object properties (names and types) but not about it's internal implementation, while data source object can have no knowledge about XAML at all. So
there should be no calls from data object to FrameworkElements like MathBox.Text
it's considered a good design to have data object class completely separate from the page or control class.
Hope this helps.
You haven't initialized your PropertyChanged event anywhere, so it will never be called. Declare and initialize it like so:
public event PropertyChangedEventHandler PropertyChanged = delegate { };
A TextBox bound to the calculated property QuickMath should receive PropertyChanged event from it in order to update the text in the field.
Despite your OrderScreen implementing the INotifyPropertyChanged interface, it will not raise the event when QuickMath is changed because its setter (where the raising of the event is located) is never called. You can fix it, for example, by calling the QuickMath setter from the independent properties setters as suggested in other answers or delegate that work to DependenciesTracking lib:
public class OrderScreen : INotifyPropertyChanged
{
private readonly IDependenciesMap<OrderScreen> _dependenciesMap =
new DependenciesMap<OrderScreen>()
.AddDependency(i => i.QuickMath, i => i.BoundNumber + i.BoundNumber2, i => i.BoundNumber, i => i.BoundNumber2);
public OrderScreen() => _dependenciesMap.StartTracking(this);
private int _boundNumber2;
private int _boundNumber;
private int _quickMath;
public int QuickMath
{
get => _quickMath;
private set
{
if (value != _quickMath)
{
_quickMath = value;
OnPropertyChanged();
}
}
}
public int BoundNumber
{
get => _boundNumber;
set
{
if (_boundNumber != value)
{
_boundNumber = value;
OnPropertyChanged();
}
}
}
public int BoundNumber2
{
get => _boundNumber2;
set
{
if (_boundNumber2 != value)
{
_boundNumber2 = value;
OnPropertyChanged();
}
}
}
public event PropertyChangedEventHandler? PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string? propertyName = null) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public class Tests_SO_56623403
{
[Test]
public void Test_SO_56623403()
{
var sut = new OrderScreen();
var raisedEventsCount = 0;
sut.PropertyChanged += (_, args) =>
{
if (args.PropertyName == nameof(OrderScreen.QuickMath))
++raisedEventsCount;
};
Assert.Multiple(() =>
{
Assert.That(sut.QuickMath, Is.EqualTo(0));
Assert.That(raisedEventsCount, Is.EqualTo(0));
});
sut.BoundNumber = 12;
Assert.Multiple(() =>
{
Assert.That(sut.QuickMath, Is.EqualTo(12));
Assert.That(raisedEventsCount, Is.EqualTo(1));
});
sut.BoundNumber2 = 40;
Assert.Multiple(() =>
{
Assert.That(sut.QuickMath, Is.EqualTo(52));
Assert.That(raisedEventsCount, Is.EqualTo(2));
});
}
}

Bound target not updating when button pressed to change value

I have some code which uses a form. The form is bound to my class, FormData. I have binding working well and updating my formData (local instance), but when I try to change the value of one of the variables in formData on button click/LostFocus trigger, it doesn't update.
Here's my relevant XAML:
<TextBox x:Name="friendly_name_textBox"
Style="{StaticResource TextErrorStyle}"
Text="{Binding
PrimaryUserName,
Mode=TwoWay,
ValidatesOnExceptions=True,
ValidatesOnDataErrors=True,
UpdateSourceTrigger=PropertyChanged,
NotifyOnValidationError=True}"
HorizontalAlignment="Left"
Margin="0,75,0,0"
TextWrapping="Wrap"
VerticalAlignment="Top"
Width="120"/>`
The button trigger (which does get run):
private void Button_Click(object sender, RoutedEventArgs e)
{
formData.PrimaryUserName = "TEST";
}
And my FormData code:
public string PrimaryUserName
{
get
{
return primaryUserNameValue;
}
set
{
if(primaryUserNameValue != value)
{
primaryUserNameValue = value;
}
}
}
You need to implement the INotifyPropertyChanged interface and raise the PropertyChanged event in your formData class:
public class formData : INotifyPropertyChanged
{
private string primaryUserNameValue;
public string PrimaryUserName
{
get
{
return primaryUserNameValue;
}
set
{
if (primaryUserNameValue != value)
{
primaryUserNameValue = value;
NotifyPropertyChanged();
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
Your Class needs to implement INotifyPropertyChanged, so that the target knows if the source property changes:
https://learn.microsoft.com/en-us/dotnet/framework/wpf/data/how-to-implement-property-change-notification
It's really easy, please have a look at the documentation and adjust your code accordingly. Your Property would have to look like this:
public string PrimaryUserName
{
get
{
return primaryUserNameValue;
}
set
{
if(primaryUserNameValue != value)
{
primaryUserNameValue = value;
OnPropertyChanged("PrimaryUserName");
}
}
}
But you also need the event and onPropertyChanged function to make it work.
Happy Coding!

How to update listbox with progress bar GUI during execution

I have a listbox in a wpf window thats bound to a list in a viewmodel object. When I run a method in the viewmodel object it processes members of the list and each member has a progress. I would like to have the gui update continuously during execution. As it is now, it only updates gui when the processing is finished.
Here I have tried to create a small example of what I have right now:
MainWindow.xaml:
<Window x:Class="WPF_MVVM_Thread_Progressbar.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WPF_MVVM_Thread_Progressbar"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:TestViewModel/>
</Window.DataContext>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="8*"/>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="8*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ListBox Grid.Column="0" Grid.Row="0" Margin="5" ItemsSource="{Binding TestWorker.TestList}">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<ProgressBar Minimum="0" Maximum="100" Value="{Binding Progress, Mode=OneWay}" Background="Bisque">
<ProgressBar.Style>
<Style TargetType="{x:Type ProgressBar}">
<Style.Triggers>
<DataTrigger Binding="{Binding Progress}" Value="0">
<Setter Property="Visibility" Value="Hidden"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ProgressBar.Style>
</ProgressBar>
<TextBlock FontWeight="Bold" Text="{Binding Path=Name}" Background="Transparent"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button Grid.Column="0" Grid.Row="1" Content="TestRun" Command="{Binding TestRunCommand}"></Button>
<TextBlock Text="{Binding SelectedIdx}" Grid.Column="1" Grid.Row="1"/>
</Grid>
</Window>
MainWindowl.xaml.cs:
using Prism.Commands;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
namespace WPF_MVVM_Thread_Progressbar
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
public class TestViewModel : INotifyPropertyChanged
{
private WorkingClass _testWorker;
private DelegateCommand _testRunCommand;
public DelegateCommand TestRunCommand
{
get { return _testRunCommand; }
set { _testRunCommand = value; }
}
public WorkingClass TestWorker
{
get { return _testWorker; }
set { _testWorker = value; RaisePropertyChanged("TestWork"); }
}
private int _selectedIdx;
public int SelectedIdx
{
get { return _selectedIdx; }
set { _selectedIdx = value; RaisePropertyChanged("SelectedIdx"); }
}
public TestViewModel()
{
_testWorker = new WorkingClass();
_testRunCommand = new DelegateCommand(TestRun, canRun);
}
public async void TestRun()
{
//await Task.Run(() => _testWorker.Work());
_testWorker.Work();
}
private bool canRun()
{
return true;
}
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
public class WorkingClass : INotifyPropertyChanged
{
private ObservableCollection<TestObject> _testList;
public ObservableCollection<TestObject> TestList
{
get { return _testList; }
set { _testList = value; RaisePropertyChanged("TestList"); }
}
public WorkingClass()
{
_testList = new ObservableCollection<TestObject>();
_testList.Add(new TestObject("Object A"));
_testList.Add(new TestObject("Object B"));
_testList.Add(new TestObject("Object C"));
RaisePropertyChanged("TestList");
}
public void Work()
{
foreach (var obj in TestList)
{
obj.TestWork();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
public class TestObject : INotifyPropertyChanged
{
private string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
private int _progress;
public int Progress
{
get { return _progress; }
set { _progress = value; RaisePropertyChanged("Progress"); }
}
public TestObject(string name)
{
this._name = name;
_progress = 0;
}
public void TestWork()
{
for (int i = 0; i < 100; i++)
{
System.Threading.Thread.Sleep(10);
Progress++;
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
I have tried to use ObservableCollection and INotifyPropertyChanged but this it seems not to be enough.
Eventually I would like to be able to have the same effect using async/await call from the TestViewModel.TestRun().
Could someone perhaps offer some insights on this? It would be much appreciated.
I think the current reason that you have the UI only updating once completed, is that you are running all of this on the UI thread. I would instead try this:
Task.Run(async delegate
{
await _testWorker.Work();
});
Or
Task.Run(() =>
{
_testWorker.Work();
});
Or
Task.Factory.StartNew(() =>
{
_testWorker.Work();
});
Or
var newThread = new Thread(new ThreadStart(_testWorker.Work());
newThread.Start();
This will return back to the UI instantly but allow your code to continue.
Note: You will have to be careful about the use of objects off the UI thread. ObservableCollections can only be created on the same thread as the dispatcher that handles the UI work. If you are using two-way binding, again you have to be careful about thread safety.
I've successfully done this in the past using a BackgroundWorker.
public class TestObject : INotifyPropertyChanged {
private BackgroundWorker worker;
public TestObject() {
worker = new BackgroundWorker() {
WorkerReportsProgress = true
};
worker.DoWork += DoWork;
worker.ProgressChanged += WorkProgress;
worker.RunWorkerCompleted += WorkFinished;
}
public int Progress
{
get { return _progress; }
set { _progress = value; RaisePropertyChanged("Progress"); }
}
// Begin doing work
public void TestWork() {
worker.RunWorkerAsync();
}
private void DoWork(object sender, DoWorkEventArgs eventArgs) {
worker.ReportProgress(0, "Work started");
for (int i = 0; i < 100; i++) {
System.Threading.Thread.Sleep(10);
worker.ReportProgress(i, "Message");
}
}
// Fires when the progress of a job changes.
private void WorkProgress(object sender, ProgressChangedEventArgs e) {
// Do something with the progress here
Progress = e.ProgressPercentage;
}
// Fires when a job finishes.
private void WorkFinished(object sender, RunWorkerCompletedEventArgs e) {
// The work finished. Do something?
}
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string propertyName)
{
// NOTE: If you're running C#6 use the null conditional operator for this check.
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(e));
}
}
A BackgroundWorker basically runs everything on a separate thread and reports back when its progress changes or it finishes working. You can pull out the ProgressPercentage from its progress report and use that in the UI. Hope that helps. To keep the example simple I didn't include some of your code but that should given you an idea of how it can be done.

Label that counts when button is pushed doesn't work in WPF following MVVM pattern

I'm a C# newbie and I'm trying to make a simple program that has two buttons and a label. Buttons are "up" and "down", and the number in the label changes according to them. When I execute the program, label shows the initial value which defined in viewmodel. But when I push buttons, it doesn't update the value. I couldn't figure out which is not working, buttons or label when an update occurs. Thanks for your time.
I think the problem is the usage "RaisePropertyChanged". I have no idea how should I use it. If someone explains it, it would be good.
Buttons and Label in view:
<Button x:Name="Up" Content="Up" HorizontalAlignment="Left" Grid.Row="6" Grid.Column="1" VerticalAlignment="Top" Width="75" Grid.ColumnSpan="2" Command="{Binding UpCommand}"/>
<Button x:Name="Down" Content="Down" Grid.Column="3" HorizontalAlignment="Left" Grid.Row="6" VerticalAlignment="Top" Width="75" Command="{Binding DownCommand}" />
<Label x:Name="Number" HorizontalAlignment="Left" Height="31" Grid.Row="4" VerticalAlignment="Top" Width="161" Content="{Binding Path=Lol, UpdateSourceTrigger=PropertyChanged}" Background="#FFB95151" Grid.ColumnSpan="3" Grid.Column="1" />
this is ViewModel:
class MainViewModel : BaseINPC
{
//Number class to hold the number
private Number lol; //I'm not good at naming
public Number Lol
{
get
{
return lol;
}
set
{
lol = value;
RaisePropertyChanged("Lol");
}
}
public MainViewModel()
{
lol = new Number { number = 5 }; //initial value
RaisePropertyChanged("Lol");
}
#region Commands
//Up botton commands
void UpNumber()
{
lol.change(true); //it adds 1 to number when True, substracts 1 when false
RaisePropertyChanged("Lol");
}
bool CanUpNumber()
{
return true;
}
public DelegateCommand UpCommand { get { return new DelegateCommand(UpNumber, CanUpNumber); } }
//Down button
void DownNumber()
{
lol.change(false);
RaisePropertyChanged("Lol");
}
bool CanDownNumber()
{
return true;
}
public DelegateCommand DownCommand { get { return new DelegateCommand(DownNumber, CanDownNumber); } }
#endregion
}
This is in my Model :
class Number : INotifyPropertyChanged
{
private int _number;
public int number
{
get { return _number; }
set
{
_number = value;
}
}
protected void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
public void change(bool up)
{
if (up)
_number++;
else
_number--;
}
public override String ToString()
{
return "" + _number;
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
in your Number class
public void change(bool up)
{
if (up)
_number++;
else
_number--;
RaisePropertyChanged("number");
}
or
public int number
{
get { return _number; }
set
{
_number = value;
RaisePropertyChanged("number");
}
}
public void change(bool up)
{
if (up)
number++;
else
number--;
}
you were missing notification for the number property
also change the content binding of Label to Content="{Binding Path=Lol.number}" since number is the real property which actually change when method change() is executed.
Lol may not necessary to be notified if not changing while runtime, also UpdateSourceTrigger=PropertyChanged is unrelevant with binding to label so perhaps remove that too.

WPF Data bound ProgressBar not showing progress

I am having troubles with getting the ProgressBar working.
XAML:
<ProgressBar x:Name="ProgressBar" Value="{Binding Progress, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Left" Height="37" Margin="10,35,0,0" VerticalAlignment="Top" Width="590"/>
Code behind:
ProgressBar.DataContext = progressModel;
IProgressModel:
public interface IProgressModel
{
double Minimum { get; set; }
double Maximum { get; set; }
double Progress { get; }
}
Implementation:
private void WorkerOnDoWork(object sender, DoWorkEventArgs doWorkEventArgs)
{
Minimum = 0;
Maximum = RenamableFiles.Count;
var i = 0;
foreach (var renamableFile in RenamableFiles)
{
var oldFilename = ReCreateOldFileName(renamableFile);
var renameProposalFilename = CreateNewFileName(renamableFile);
if (oldFilename != null && renameProposalFilename != null && !oldFilename.Equals(renameProposalFilename))
{
// File.Move(oldFilename, renameProposalFilename);
Thread.Sleep(100);
Progress = i++;
}
}
}
And the pretty straight forward PropertyChanged mechanism:
private double _progress;
public double Progress
{
get { return _progress; }
set
{
_progress = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
The ProgressBar starts "full" and remains that way throughout the process. I have read all related threads on SO, but no luck.
What am I doing wrong?
Thx in advance.
You need to bind your maximum, too:
<ProgressBar x:Name="ProgressBar"
Value="{Binding Progress}"
Maximum="{Binding Maximum}"
Minimum="{Binding Minimum}"
HorizontalAlignment="Left" Height="37" Margin="10,35,0,0"
VerticalAlignment="Top" Width="590"/>

Categories