WPF -我试图将一个进度条值绑定到一个基于2个文本框计算百分比的方法-所有文本框都在一个treeviewitem中

fruv7luv  于 2023-04-13  发布在  其他
关注(0)|答案(2)|浏览(167)

我目前的具体问题是,我试图通过将进度条绑定到一个返回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);
        }
    }

我希望在“总小时数”文本框中输入一个数字,然后在“剩余小时数”文本框中输入一个数字,然后看到百分比栏反映进度。

lztngnrs

lztngnrs1#

你不绑定到方法。你绑定到属性。当属性引发INotifyPropertyChanged.PropertyChanged事件时,绑定会自动更新。
您可以用途:

public int ProgressPercentage
{
        get
        {
            if(this.HrsTotal != 0)
            {
                return 100 -((this.HrsRemaining / this.HrsTotal) * 100);
            }
            else { return 0; }
            
        }
}

并在HrsRemainingHrsTotal发生变化时调用OnPropertyChanged(nameof(ProgressPercentage))

j2qf4p5b

j2qf4p5b2#

感谢@LaniusExcubitor我能够得到我想要的。我只需要添加ProgressPercentage作为属性,并添加一个方法来计算百分比,然后使用输出设置ProgressPercentage变量。

public float HrsTotal
    {
        get { return _hrsTotal; }
        set
        {
            _hrsTotal = value;
            CalculatePercent();
            this.NotifyPropertyChanged(nameof(ProgressPercentage));
        }
    }
    public float HrsRemaining
    {
        get { return _hrsRemaining; }
        set
        {
            _hrsRemaining = value;
            CalculatePercent();
            this.NotifyPropertyChanged(nameof(ProgressPercentage));
        }
    }

    public double ProgressPercentage
    {
        get 
        {
            return this._progressPercentage;
        }
        set
        {
            this._progressPercentage = value;
        }
    }

    private void CalculatePercent()
    {
        ProgressPercentage = 100 - (HrsRemaining / HrsTotal * 100);
    }

相关问题