0

我正在尝试创建一个状态窗口,向用户显示当前正在运行的任务数。每个任务都被添加到 ObservableCollection 中,并且我在窗口 XAML 中设置了绑定路径,但该框不会更新。我已经广泛搜索了有关如何完成此操作的良好工作示例或教程,但我找不到任何东西。我究竟做错了什么?顺便说一下,它是一个连接到我们办公室的每台 Cisco Switch 并下载配置文件的程序。

窗口 XAML:

<Window x:Class="BackupCiscoConfigs.ProcessRunning"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:c="clr-namespace:BackupCiscoConfigs"
        Title="ProcessRunning" Height="300" Width="300"
        Closed="Window_Closed" ResizeMode="CanMinimize">

    <Grid>
        <Button Content="Run" Height="23" HorizontalAlignment="Center" Margin="0,0,0,0" Name="btnRun" VerticalAlignment="Bottom" Width="75" Click="btnRun_Click" />
        <TextBlock Width="200" Height="85" Margin="35,80,43,65" Text="{Binding Mode=OneWay, Path=d1.results.Count}"></TextBlock>
    </Grid>
</Window>

窗口代码隐藏:

namespace BackupCiscoConfigs
{
    /// <summary>
    /// Interaction logic for ProcessRunning.xaml
    /// </summary>
    public partial class ProcessRunning : Window
    {
        private MainWindow m_parent;
        private Configuration currentConfig;
        public DeviceInterface di;

        public ProcessRunning(MainWindow parent)
        {
            currentConfig = Configuration.loadConfig();
            m_parent = parent;
            InitializeComponent();
        }

        private void btnRun_Click(object sender, RoutedEventArgs e)
        {
            List<Device> devices = currentConfig.devices;
            di = new DeviceInterface(currentConfig.tftpIP,
                currentConfig.tftpDIR, currentConfig.cmd);
            di.RunCommands(devices);
        }
    }
}

生成任务的类:

namespace BackupCiscoConfigs
{
    public class DeviceInterface
    {
        private string tftpIP;
        private string tftpDIR;
        private string command;
        private string dirDate;
        public ObservableCollection<Task> results { get; set; }

        public DeviceInterface(string tftpIP, string tftpDIR, string cmd)
        {
            this.tftpIP = tftpIP;
            this.tftpDIR = tftpDIR;
            this.command = cmd;
            dirDate = DateTimeOffset.Now.ToString("MM.dd.yyyy.HH.mm.ss");
            Directory.CreateDirectory(tftpDIR + dirDate);
        }

        public void RunCommands(List<Device> devices)
        {
            results = new ObservableCollection<Task>();
            foreach (Device d in devices)
            {
                Device d1 = d;
                d1.command = command + " tftp://" + tftpIP + "/" + dirDate + "/" + d1.ip + ".cfg";
                results.Add(Task<string>.Factory.StartNew(() => d1.BackupDevice()));
            }
            string res = "";
            foreach (Task<string> t in results)
            {
                string message = t.Result + "\n";
                res += message;
            }
            MessageBoxResult msg = MessageBox.Show(res);
        }
    }
}
4

2 回答 2

1
<Window x:Class="BackupCiscoConfigs.ProcessRunning"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:c="clr-namespace:BackupCiscoConfigs"
        Title="ProcessRunning" Height="300" Width="300"
        Closed="Window_Closed" ResizeMode="CanMinimize">
    <Grid DataContext="{Binding RelativeSource={RelativeSource Mode=Self}}">
        <Button Content="Run" Height="23" HorizontalAlignment="Center" Margin="0,0,0,0" Name="btnRun" VerticalAlignment="Bottom" Width="75" Click="btnRun_Click" />
        <TextBlock Width="200" Height="85" Margin="35,80,43,65" Text="{Binding Mode=OneWay, Path=Results.Count}"></TextBlock>
    </Grid>
</Window>

窗口代码隐藏:

namespace BackupCiscoConfigs
{
    /// <summary>
    /// Interaction logic for ProcessRunning.xaml
    /// </summary>
    public partial class ProcessRunning : Window, INotifyPropertyChanged
    {
        private MainWindow m_parent;
        private Configuration currentConfig;
        private DeviceInterface di;
        public event PropertyChangedEventHandler PropertyChanged;

        // This method is called by the Set accessor of each property. 
        // The CallerMemberName attribute that is applied to the optional propertyName 
        // parameter causes the property name of the caller to be substituted as an argument. 
        private void NotifyPropertyChanged(String propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        private ObservableCollection<Task> _results;
        public ObservableCollection<Task> Results
        get
        {
            return _results;
        }
        set
        {
            _results= value;
            NotifyPropertyChanged("results");
        }

        public ProcessRunning(MainWindow parent)
        {
            currentConfig = Configuration.loadConfig();
            m_parent = parent;
            InitializeComponent();
        }

        private void btnRun_Click(object sender, RoutedEventArgs e)
        {
            List<Device> devices = currentConfig.devices;
            di = new DeviceInterface(currentConfig.tftpIP,
                currentConfig.tftpDIR, currentConfig.cmd);
            di.RunCommands(devices);
            Results = di.results;
        }
    }
}
于 2013-02-07T15:24:39.633 回答
0

我可以立即看到两个问题:

  1. 我看不到您DataContext为这条工作路径设置的位置:Path=d1.results.Count
  2. 您正在更新results属性,但您没有实施INotifyPropertyChanged,这意味着 WPF 永远不会知道您已将新对象挂接ObservableCollection到结果中。
于 2013-02-07T15:25:16.263 回答