WPF TabControl绑定不允许我更新选项卡数据。

18 浏览
0 Comments

WPF TabControl绑定不允许我更新选项卡数据。

我有一个大学作业,要用WPF创建一个类似Notepad++的应用程序。为此,我在MainWindow.xaml中创建了一个TabControl,每个选项卡都有一个标题(TextBlock)和文本内容(TextBox)。TabControl绑定到名为"Tabs"的TabModel(我用于选项卡项的模型类)的ObservableCollection。

问题出现在调用"另存为"函数时。它应该将选项卡内容保存到一个.txt文件中(这部分工作正常),并将活动选项卡的标题重命名为保存的.txt文件的名称(它不会更新标题)。调试显示,"Tabs"中的数据被正确更新,但UI没有反映出来。

这是MainWindow.xaml中的代码:


    
        
    
    
        
            
                
                
            
        
        
            
            
        
        
            
                
                    
                
            
            
                
                
                
                
                
                
            
            
                
                
                
            
            
                
            
        
        
            
                
                    
                
            
            
                
                    
                
            
        
    

这是FileCommands.cs中的代码,我在其中进行了绑定和实现SaveAs函数。我排除了"using"部分的代码:

namespace Notepad__.Commands
{
    class FileCommands : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public ObservableCollection Tabs { get; set; }
        private int currentTab;
        public int CurrentTab { get => currentTab; set => SetProperty(ref currentTab, value); }
        private ICommand m_new;
        private ICommand m_open;
        private ICommand m_saveAs;
        public FileCommands()
        {
            Tabs = new ObservableCollection();
            Tabs.Add(new TabModel { Filename = "File 1", Content = "" });
        }
        private void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        public void New(object parameter)
        {
            Tabs.Add(new TabModel { Filename = "File " + (Tabs.Count + 1), Content = "" });
        }
        public void Open(object parameter)
        {
            var openFileDialog = new OpenFileDialog
            {
                Title = "Select a text file...",
                Filter = "Text files (*.txt)|*.txt|All files (*.*)|*.*"
            };
            if (openFileDialog.ShowDialog() == true)
            {
                Stream fileStream = openFileDialog.OpenFile();
                using (StreamReader reader = new StreamReader(fileStream))
                {
                    Tabs.Add(new TabModel { Filename = openFileDialog.SafeFileName, Content = reader.ReadToEnd() });
                    OnPropertyChanged("Tabs");
                }
            }
        }
        public void SaveAs(object parameter)
        {
            var saveFileDialog = new SaveFileDialog
            {
                Title = "Save...",
                Filter = "Text files (*.txt)|*.txt|All files (*.*)|*.*"
            };
            if (saveFileDialog.ShowDialog() == true)
            {
                File.WriteAllText(saveFileDialog.FileName, Tabs[currentTab].Content);
                Tabs[currentTab].Filename = saveFileDialog.SafeFileName;
            }
            OnPropertyChanged("Tabs");
        }
        public ICommand CommandNew
        {
            get
            {
                if (m_new == null)
                    m_new = new RelayCommand(New);
                return m_new;
            }
        }
        public ICommand CommandOpen
        {
            get
            {
                if (m_open == null)
                    m_open = new RelayCommand(Open);
                return m_open;
            }
        }
        public ICommand CommandSaveAs
        {
            get
            {
                if (m_saveAs == null)
                    m_saveAs = new RelayCommand(SaveAs);
                return m_saveAs;
            }
        }
        protected bool SetProperty(ref T field, T newValue, [CallerMemberName] string propertyName = null)
        {
            if (!Equals(field, newValue))
            {
                field = newValue;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
                return true;
            }
            return false;
        }
    }
}

我还包括了"New"和"Open"函数的代码,因为它们工作正常,使用Tabs.Add添加新选项卡按预期工作,UI也会相应地更新。这就是让我困惑的地方:为什么添加选项卡可以,而更新选项卡不行?

如果有什么我应该包含的代码,请告诉我,谢谢阅读:)

0
0 Comments

WPF TabControl绑定不允许我更新选项卡数据的问题出现的原因是,TabModel需要实现INotifyPropertyChanged接口,以便在每次更改属性值时更新UI。解决方法是创建一个专门用于引发通知的基类。

以下是一个示例:

基类:

internal abstract class ObservableBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected bool SetProperty(ref T field, T newValue, [CallerMemberName] string propertyName = null)
    {
        if (Equals(field, newValue))
            return false;
        field = newValue;
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        return true;
    }
}

从基类派生的模型:

internal class TabModel : ObservableBase
{
    private string _name;
    private string _content;
    public string Filename
    {
        get => _name;
        set => SetProperty(ref _name, value);
    }
    public string Content
    {
        get => _content;
        set => SetProperty(ref _content, value);
    }
}

VM也是一样的:

class FileCommands : ObservableBase
{
    // ...
}

通过实现INotifyPropertyChanged接口和使用ObservableBase基类,可以解决WPF TabControl绑定不允许更新选项卡数据的问题。

0