将ObservableCollection从Object内部绑定到ListView的问题

时间:2013-05-29 05:37:30

标签: c# wpf binding observablecollection inotifypropertychanged

我的WPF ListView

        <ListView Name="lstTasks" ItemContainerStyle="{StaticResource itemstyle}" ItemsSource="{Binding ElementName=TaskFile,Path=obscollFiles}" SelectionMode="Single">
           <ListView.View>
               <GridView>
                    <GridViewColumn Header="Id" DisplayMemberBinding="{Binding TaskId}" />
                    <GridViewColumn Header="Datum" DisplayMemberBinding="{Binding TaskDate,StringFormat={}{0:dd.MM.yyyy}}" />
                    <GridViewColumn Header="Startzeit" DisplayMemberBinding="{Binding TaskStartTime,StringFormat=t}" />
                    <GridViewColumn Header="Endzeit" DisplayMemberBinding="{Binding TaskEndTime,StringFormat=t}" />
                    <GridViewColumn Header="Dauer" DisplayMemberBinding="{Binding TaskDuration}" />
                    <GridViewColumn Header="Task" DisplayMemberBinding="{Binding TaskString}" />
               </GridView>
           </ListView.View>
       </ListView>

我只想将此ListVIew绑定(正如您对上面的代码所期望的那样:

    public class csTaskFileInfo
{
    public DateTime DateOfTasks { get; set; }
    public ObservableCollection<csTask> obscollTasks { get; set; }

    public csTaskFileInfo()
    {
        obscollTasks = new ObservableCollection<csTask>();
    }
}

来自ObservableCollection的csTask类:

[Serializable]
public class csTask:INotifyPropertyChanged
{
    private int _TaskId;
    private string _TaskString;
    private DateTime _TaskDate;
    private TimeSpan _TaskStartTime;
    private TimeSpan _TaskEndTime;
    private TimeSpan _TaskDuration;

    [XmlIgnore]
    public TimeSpan TaskDuration
    {
        get { return _TaskDuration; }
        set
        {
            _TaskDuration = value;
            Notify("TaskDuration");
        }
    }
    [XmlIgnore]
    public TimeSpan TaskEndTime
    {
        get { return _TaskEndTime; }
        set
        {
            _TaskEndTime = value;

            if (TaskEndTime > TaskStartTime)
            {
                TaskDuration = TaskEndTime - TaskStartTime;
            }

            Notify("TaskEndTime");
        }
    }
    [XmlIgnore]
    public TimeSpan TaskStartTime
    {
        get { return _TaskStartTime; }
        set
        {
            _TaskStartTime = value;

            if (_TaskStartTime < _TaskEndTime)
            {
                TaskDuration = TaskEndTime - TaskStartTime;
            }

            Notify("TaskStartDate");
        }
    }
    public DateTime TaskDate
    {
        get { return _TaskDate; }
        set
        {
            _TaskDate = value;
            Notify("TaskDate");
        }
    }

    [XmlElement("TaskDurationString")]
    public string TaskDurationString { get { return TaskDuration.ToString(); } set { TaskDuration = TimeSpan.Parse(value); } }
    [XmlElement("TaskEndTimeString")]
    public string TaskEndTimeString { get { return TaskEndTime.ToString(); } set { TaskEndTime = TimeSpan.Parse(value); } }
    [XmlElement("TaskStartTimeString")]
    public string TaskStartTimeString { get { return TaskStartTime.ToString(); } set { TaskStartTime = TimeSpan.Parse(value); } }


    public string TaskString
    {
        get { return _TaskString; }
        set
        {
            _TaskString = value;
            Notify("TaskString");
        }
    }
    public int TaskId
    {
        get { return _TaskId; }
        set
        {
            _TaskId = value;
            Notify("TaskId");
        }
    }

    public csTask(int TaskId, string TaskString,DateTime TaskDate)
    {
        this.TaskId = TaskId;
        this.TaskString = TaskString;
        this.TaskDate = TaskDate;
    }

    public csTask()
    {

    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void Notify(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

如您所见,INotifyPropertyChanged已经实现。 我为什么有点困惑的部分:

在早期版本中,当我只使用ObservableCollection时,绑定正在运行。

由于我正在使用一个Object,其中Collection存在于该Object内部,我无法使其正常工作。

有遗漏的东西吗?

我正在使用该对象的MainWindow的Datacontext已经设置为自己。

this.Datacontext = this;

某些提示或指向错误会非常好:)

非常感谢!

问候 丹尼尔

编辑:

我在csTask中实现了INotifyPropertyChanged。 (在csTaskFile里面的ObservableCollection中使用它)

我希望你的MainWindow代码:):

FileSystemWatcher FileWatcher;
    public csTaskFileInfo TaskFile { get; set; }
    public List<FileInfo> obscollFiles { get; set; }
    private string _FolderPath;
    public string FolderPath
    {
        get { return _FolderPath; }
        set
        {
            _FolderPath = value;
            Notify("FolderPath");
        }
    }
    public DirectoryInfo FolderDirectory { get; set; }

    public MainWindow()
    {
        InitializeComponent();
        TaskFile = new csTaskFileInfo();
        TaskFile.DateOfTasks = DateTime.Now;
        obscollFiles = new List<FileInfo>();
        this.DataContext = this;
        RegistryKey _RegKey = Registry.CurrentUser.OpenSubKey("Software\\WTT");

        if (_RegKey == null)
        {
            FolderPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\WTT_Files";
        }
        else
        {
            FolderPath = (string)_RegKey.GetValue("FolderDestination") + "\\WTT_Files";
        }

        if (Directory.Exists(FolderPath) == false)
        {
            Directory.CreateDirectory(FolderPath);
        }

        FolderDirectory = new DirectoryInfo(FolderPath);

        FileWatcher = new FileSystemWatcher(FolderPath,"*.xml");
        FileWatcher.Created += new FileSystemEventHandler (FileWatcher_Changed);
        FileWatcher.Deleted += new FileSystemEventHandler (FileWatcher_Changed);
        //FileWatcher.Changed += new FileSystemEventHandler(FileWatcher_Changed);
        FileWatcher.Renamed += new RenamedEventHandler(FileWatcher_Changed);
        FileWatcher.EnableRaisingEvents = true;
        FileWatcher_Changed(null,null);

        var _temp = from n in obscollFiles
                    where n.Name == (DateTime.Today.ToShortDateString() + ".xml")
                    select n;
        if (_temp.Count() == 1)
        {
            lstFiles.SelectedItem = _temp.Single() as FileInfo;
        }
    }

    private void FileWatcher_Changed(object sender, FileSystemEventArgs e)
    {
        obscollFiles = FolderDirectory.GetFiles("*.xml").ToList();
        Notify("obscollFiles");
    }

    private void NewTask_Click(object sender, RoutedEventArgs e)
    {

        TaskStringWindow _newTaskStringWindow = new TaskStringWindow();
        _newTaskStringWindow.Owner = this;
        _newTaskStringWindow.txtEingabe.Focus();
        _newTaskStringWindow.ShowDialog();

        if (_newTaskStringWindow.DialogResult == true)
        {
            csTask _newTask = new csTask();
            if (TaskFile.obscollTasks != null && TaskFile.obscollTasks.Count > 0)
            {
                csTask _previousTask;
                _previousTask = TaskFile.obscollTasks.Last();

                _previousTask.TaskEndTime = TimeSpan.Parse(DateTime.Now.ToLongTimeString());

                _newTask.TaskId = _previousTask.TaskId + 1;
                _newTask.TaskDate = TaskFile.DateOfTasks;
                _newTask.TaskStartTime = TimeSpan.Parse(DateTime.Now.ToLongTimeString());
            }
            else
            {
                _newTask.TaskId = 1;
                _newTask.TaskDate = DateTime.Now;
                _newTask.TaskStartTime = TimeSpan.Parse(DateTime.Now.ToLongTimeString());
            }
            _newTask.TaskString = _newTaskStringWindow.txtEingabe.Text;
            TaskFile.obscollTasks.Add(_newTask);
            //lstTasks.DataContext = TaskFile.obscollTasks;
        }
    }

    private void SaveCurrentFile_Click(object sender, RoutedEventArgs e)
    {
        XmlSerializer XmlSer = new XmlSerializer(typeof(csTaskFileInfo));

        if (Directory.Exists(FolderPath) == false)
        {
            Directory.CreateDirectory(FolderPath);
        }
        FileStream stream = new FileStream(FolderPath + @"\" + DateTime.Now.ToShortDateString() + ".xml", FileMode.Create);
        XmlSer.Serialize(stream, TaskFile);
        stream.Close();

    }

    private void ResetSearchByDate_Click(object sender, RoutedEventArgs e)
    {
        //lstTasks.DataContext = TaskFile.obscollTasks;
    }

    private void LoadFile_Click(object sender, RoutedEventArgs e)
    {
        OpenFileDialog OpenFile = new OpenFileDialog();
        OpenFile.Filter = ("XAML-Dateien |*.xml");
        if (OpenFile.ShowDialog(this) == true)
        {
            TaskFile.obscollTasks.Clear();
            FileInfo _tempFileInfo = new FileInfo(OpenFile.FileName);
            obscollFiles.Add(_tempFileInfo);
            lstFiles.SelectedItem = _tempFileInfo;
        }
    }

    private void LoadFile(FileInfo File)
    {
        try
        {
        //XmlSerializer XmlSer = new XmlSerializer(typeof(csTaskFileInfo));
        //FileStream stream = new FileStream(File.FullName, FileMode.Open);
        //TaskFile = (csTaskFileInfo)XmlSer.Deserialize(stream);
            using (FileStream fStream = new FileStream(File.FullName,FileMode.Open))
            {
                XmlSerializer XmlSer = new XmlSerializer(typeof(csTaskFileInfo));

                using (StreamReader sReader = new StreamReader(fStream,Encoding.UTF8))
                {
                    TaskFile = (csTaskFileInfo)XmlSer.Deserialize(sReader);
                    //lstTasks.DataContext = TaskFile.obscollTasks;
                }
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.InnerException.ToString(),"Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
        }
    }

    private void SetFolder_Click(object sender, RoutedEventArgs e)
    {
        System.Windows.Forms.FolderBrowserDialog _SelectFolder = new System.Windows.Forms.FolderBrowserDialog();

        System.Windows.Forms.DialogResult _result = _SelectFolder.ShowDialog();

        if (_result == System.Windows.Forms.DialogResult.OK)
        {
            RegistryKey _RegKey = Registry.CurrentUser.OpenSubKey("Software",true);
            _RegKey.CreateSubKey("WTT");
            _RegKey = _RegKey.OpenSubKey("WTT",true);
            _RegKey.SetValue("FolderDestination", _SelectFolder.SelectedPath);
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void Notify(string propertyName)
    {
        if (this.PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    private void lstFiles_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
    {
        TaskFile.obscollTasks.Clear();
        LoadFile(lstFiles.SelectedItem as FileInfo);
    }

    private void HandleDoubleClick(object sender,MouseButtonEventArgs e)
    {
        TaskChangeData TaskChange = new TaskChangeData(TaskFile.obscollTasks, lstTasks.SelectedItem as csTask);

        TaskChange.ShowDialog();
    }

1 个答案:

答案 0 :(得分:0)

由于obscollFiles中没有TaskFile(而obscollTasks代替),不应该是

<ListView Name="lstTasks" SelectionMode="Single"
ItemContainerStyle="{StaticResource itemstyle}" 
ItemsSource="{Binding Path=TaskFile.obscollTasks}" >
....