Все таки не могу понять, почему не работает прогрессбар. Использую MVVM WPF. Есть модель,это класс с одним методом.
namespace progresbar.Model
{
public delegate void StatusChangedHandler(int status);
public class Model
{
private int start;
private int end=100;
public event StatusChangedHandler StatusChange;
public int Startbar
{
get { return start; }
set
{
start = value;
StatusChange?.Invoke(value);
}
}
public int End
{
get { return end; }
set
{
end = value;
}
}
public void Go()
{
Task.Factory.StartNew(() =>
{
// просто метод
Startbar = 0;
while (Startbar != End)
{
Startbar++;
}
});
}
}
Есть ViewModel
class MainViewModel : INotifyPropertyChanged
{
Model.Model _model=new Model.Model();
private int _startbar;
private int _endbar;
// реализую интерфейс
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
// команда запуска
public Comand CommandToPars
{
get
{
return new Comand( () =>
{
// выполняю метод
_model.Go();
// забираю свойства
// праивльно ли так делать?
_model.StatusChange += _model_StatusChange;
_endbar = _model.End;
});
}
}
private void _model_StatusChange(int status)
{
Startbar = status;
}
// свойства для прогресбара
public int Startbar
{
get { return _startbar; }
set
{
_startbar = value;
OnPropertyChanged();
}
}
public int Endtbar
{
get { return _endbar; }
set
{
_endbar = value;
OnPropertyChanged();
}
}
public MainViewModel()
{
}
}
Есть View
<Window x:Class="progresbar.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:progresbar"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid HorizontalAlignment="Left" Height="345" Margin="10,25,0,0" VerticalAlignment="Top" Width="747">
<Button Command="{ Binding CommandToPars}" Content="Button" HorizontalAlignment="Left" Height="42" Margin="173,279,0,0" VerticalAlignment="Top" Width="389"/>
<ProgressBar Maximum="{Binding Endtbar}"
Value="{Binding StartBar}" HorizontalAlignment="Left" Height="46" Margin="94,85,0,0" VerticalAlignment="Top" Width="512"/>
</Grid>
</Grid>
</Window>
Подскажите что не так делаю, почему не работает. Прогресс бар всегда зеленый, даже когда кнопка не нажата, а при отладке все переменные вроде нормально работают.
Возьмем вашу разметку (не забудем указать минимальное значение)
<Grid HorizontalAlignment="Left" Height="345" Margin="10,25,0,0" VerticalAlignment="Top" Width="747">
<Button Command="{ Binding CommandToPars}" Content="Button" HorizontalAlignment="Left" Height="42" Margin="173,279,0,0" VerticalAlignment="Top" Width="389"/>
<ProgressBar Maximum="{Binding Endtbar}" Minimum="0"
Value="{Binding Startbar}" HorizontalAlignment="Left" Height="46" Margin="94,85,0,0" VerticalAlignment="Top" Width="512"/>
</Grid>
Модель
public delegate void StatusChangedHandler(int status);
public class Model
{
private int start;
private int end = 100;
public event StatusChangedHandler StatusChange;
public int Startbar
{
get { return start; }
set
{
start = value;
StatusChange?.Invoke(value);
}
}
public int End
{
get { return end; }
set
{
end = value;
}
}
public void Go()
{
Task.Factory.StartNew(() =>
{
// просто метод
Startbar = 0;
while (Startbar < End)
{
Thread.Sleep(100);
Startbar++;
}
});
}
}
Вьюмодель (у меня нет вашей команды, потому я свою накатал)
public class DelegateCommand : ICommand
{
private readonly Action _action;
public DelegateCommand(Action action)
{
_action = action;
}
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
_action();
}
public event EventHandler CanExecuteChanged;
}
class MainViewModel : INotifyPropertyChanged
{
Model _model = new Model();
private int _startbar;
private int _endbar = 100;
// реализую интерфейс
public event PropertyChangedEventHandler PropertyChanged;
//[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
// команда запуска
public ICommand CommandToPars
{
get
{
return new DelegateCommand(() =>
{
// выполняю метод
_model.Go();
// забираю свойства
// праивльно ли так делать?
_model.StatusChange += _model_StatusChange;
_endbar = _model.End;
});
}
}
private void _model_StatusChange(int status)
{
Startbar = status;
}
// свойства для прогресбара
public int Startbar
{
get { return _startbar; }
set
{
_startbar = value;
OnPropertyChanged();
}
}
public int Endtbar
{
get { return _endbar; }
set
{
_endbar = value;
OnPropertyChanged();
}
}
public MainViewModel()
{
}
}
Запускаем
Ну тут много чего править нужно.
Во-первых, в теле сеттера свойства должны вызывать OnPropertyChanged
с именем свойства и вообще в любом месте кода вы должны вызывать этот метод с именем. Тогда VM через событие пинает View на обновление значения.
Например:
public int StartBar
{
get { return _startbar; }
set
{
_startbar = value;
OnPropertyChanged("StartBar");
}
}
Во-вторых, как вы запускаете? У вас при нажатии кнопки последовательно:
В результате: с очень большой вероятностью, за то время, пока основной поток, после запуска нового потока дойдет до подписки на событие, созданный поток успеет пробежаться по всем значениям и в результате ты даже не словишь ни одного срабатывания.
В принципе, запомни, что любая инициализация должна происходить ДО начала работы - это в общем-то логично. То есть подписки на события, установки значения - до запуска счётчика.
Ну и в-третьих, зачем отдельно имеет поля для свойств в VM? У вас есть модель с этими значениями, поэтому берите значения оттуда. Например:
public int EndBar
{
get { return _model.End; }
set
{
_model.End = value;
OnPropertyChanged("EndBar");
}
}
Только для данного примера нужно будет менять кардинально модель и логику взаимодействия с VM, поэтому это лишь рекомендация.
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Пробовал через Vector3RotateTowards и потом его в Quarternion