我目前的具体问题是,我试图通过将进度条绑定到一个返回int的方法来更新进度条。
我正在尝试在WPF中创建一个基本的Microsoft Project风格的任务管理器作为学习练习。WPF和MVVM模式。我将“任务”添加到树视图中,并使用“添加”按钮为该“任务”创建子项。然后我希望能够输入“总小时数”和“剩余小时数”然后在进度条中看到任务完成的百分比。当我输入数字时,什么也没有发生,我真的不知道我在做什么。
MainWindow.xaml
<Window x:Class="Project_Management_App___Test_02.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:Project_Management_App___Test_02"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
DataContext="{Binding RelativeSource={RelativeSource self}}"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<StackPanel>
<DockPanel>
<Menu DockPanel.Dock="Top">
<MenuItem Header="_File">
<MenuItem Header="New" Click="MenuItem_Click" />
<MenuItem Header="Open" />
<MenuItem Header="Save" />
<Separator />
<MenuItem Header="Exit" />
</MenuItem>
</Menu>
</DockPanel>
<Grid>
<TreeView Name="treeview" Grid.Row="0">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type local:Task}" ItemsSource="{Binding Items}">
<StackPanel Orientation="Horizontal">
<Label>Task Name</Label>
<TextBox Width="120" VerticalAlignment="Center" Text="Text Goes here"></TextBox>
<ProgressBar Width="200" Height="10" Value="{Binding Path=GetProgressPercentage}" Margin="4"></ProgressBar>
<Label>Hours Total</Label>
<TextBox Width="30" VerticalAlignment="Center" Text="{Binding Path=HrsTotal, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
</TextBox>
<Label>Hours Remaining</Label>
<TextBox Width="30" VerticalAlignment="Center" Text="{Binding HrsRemaining, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBox>
<Button Margin="4" Width="20" Command="{Binding Path=AddBtnClick}" >+</Button>
<Button Margin="4" Width="20" Command="{Binding Path=DelBtnClick}" >-</Button>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
<TreeView.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Setter Property="IsExpanded" Value="{Binding IsExpanded}"/>
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
</Grid>
</StackPanel>
</Window>
Task.cs
class Task : TreeViewItemBase
{
public Task()
{
this.Items = new ObservableCollection<Task>();
}
public ObservableCollection<Task> Items { get; set; }
public ObservableCollection<Task> ParentItems { get; set; }
private int _hrsTotal;
private int _hrsRemaining;
public int HrsTotal
{
get { return _hrsTotal; }
set
{
if (_hrsTotal != value)
{
_hrsTotal = value;
this.NotifyPropertyChanged("HrsTotal");
}
}
}
public int HrsRemaining
{
get { return _hrsRemaining; }
set
{
if (_hrsRemaining != value)
{
_hrsRemaining = value;
this.NotifyPropertyChanged("HrsRemaining");
}
}
}
public int GetProgressPercentage()
{
if(this.HrsTotal != 0)
{
return 100 -((this.HrsRemaining / this.HrsTotal) * 100);
}
else { return 0; }
}
private ICommand _addBtnClick;
private ICommand _delBtnClick;
public ICommand AddBtnClick
{
get
{
if(_addBtnClick == null)
{
_addBtnClick = new RelayCommand(param => this.AddNewTask(), param => this.CanAddTask());
}
return _addBtnClick;
}
}
public ICommand DelBtnClick
{
get
{
if(_delBtnClick == null)
{
_delBtnClick = new RelayCommand(param => this.DeleteTask(), param => this.CanDelTask());
}
return _delBtnClick;
}
}
private bool CanAddTask()
{
return true;
}
private bool CanDelTask()
{
if(ParentItems != null) { return true; }
else { return false; }
}
public void AddNewTask()
{
Task newTask = new Task();
newTask.ParentItems = this.Items;
this.Items.Add(newTask);
this.IsExpanded = true;
}
public void DeleteTask()
{
ParentItems.Remove(this);
}
}
TreeViewItemBase.cs
class TreeViewItemBase : INotifyPropertyChanged
{
private bool isExpanded;
public bool IsExpanded
{
get { return this.isExpanded; }
set
{
if(value != this.isExpanded)
{
this.isExpanded = value;
NotifyPropertyChanged("IsExpanded");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propName)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
}
RelayCommand.cs
class RelayCommand : ICommand
{
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
public RelayCommand(Action<object> execute) : this(execute, null) { }
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
if(execute == null)
{
throw new ArgumentNullException("execute");
}
_execute = execute; _canExecute = canExecute;
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute(parameter);
}
public void Execute(object parameter)
{
_execute(parameter);
}
}
我希望在“总小时数”文本框中输入一个数字,然后在“剩余小时数”文本框中输入一个数字,然后看到百分比栏反映进度。
2条答案
按热度按时间lztngnrs1#
你不绑定到方法。你绑定到属性。当属性引发
INotifyPropertyChanged.PropertyChanged
事件时,绑定会自动更新。您可以用途:
并在
HrsRemaining
或HrsTotal
发生变化时调用OnPropertyChanged(nameof(ProgressPercentage))
。j2qf4p5b2#
感谢@LaniusExcubitor我能够得到我想要的。我只需要添加ProgressPercentage作为属性,并添加一个方法来计算百分比,然后使用输出设置ProgressPercentage变量。