为什么这些选项卡似乎共享同一个文本框?

本文关键字:同一个 共享 文本 选项 为什么 | 更新日期: 2023-09-27 17:54:08

我在xaml中定义了我的UI,下面是我的代码:

<TabControl HorizontalAlignment="Left" Height="330" VerticalAlignment="Top" Width="764" Margin="10,10,0,0" ItemsSource="{Binding AllTabs}" SelectedItem="{Binding SelectedTab}">
        <TabControl.ItemContainerStyle>
            <Style TargetType="TabItem">
                <Setter Property="Header" Value="{Binding Header}"/>
                <Setter Property="Content">
                    <Setter.Value>
                        <Grid>
                            <TextBox Text="{Binding Text}" FontSize="16" AcceptsReturn="True" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
                            </TextBox>
                        </Grid>
                    </Setter.Value>
                </Setter>
                <Setter Property="FontSize" Value="20"/>
            </Style>
        </TabControl.ItemContainerStyle>
    </TabControl>

当我运行程序时。我可以毫无问题地添加许多标签。标题是不同的,但每当我改变其中一个选项卡中的文本框的内容时,其他选项卡中的所有文本框都更改为相同的内容(似乎它们都共享相同的文本框,或绑定到相同的源,这很奇怪)。

我在定义UI时犯了错误吗?请帮助我,并提前感谢。

这是我的模型,非常简单:

using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
namespace MyHomework__MVVM_
{
    class MyHomeworkModel : INotifyPropertyChanged
    {
        private string header, text;
        public event PropertyChangedEventHandler PropertyChanged;
        public string Header
        {
            get
            {
                return header;
            }
            set
            {
                header = value;
                OnPropertyChanged("Header");
            }
        }
        public string Text
        {
            get
            {
                return text;
            }
            set
            {
                text = value;
                OnPropertyChanged("Text");
            }
        }
        private void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

我的viewmodel,仍然很简单:

using MyHomework;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows.Input;
namespace MyHomework__MVVM_
{
    class MyHomeworkViewModel : INotifyPropertyChanged
    {
        private ObservableCollection<MyHomeworkModel> allTabs;
        private MyHomeworkModel selectedTab;
        public event PropertyChangedEventHandler PropertyChanged;
        public MyHomeworkViewModel()
        {
            allTabs = new ObservableCollection<MyHomeworkModel>();
            selectedTab = new MyHomeworkModel();
            AddCourseCommand = new AddCourseCommand(this);
        }
        public ObservableCollection<MyHomeworkModel> AllTabs
        {
            get
            {
                return allTabs;
            }
            set
            {
                allTabs = value;
                OnPropertyChanged("AllTabs");
            }
        }
        public MyHomeworkModel SelectedTab
        {
            get
            {
                return selectedTab;
            }
            set
            {
                selectedTab = value;
                OnPropertyChanged("SelectedTab");
            }
        }
        public ICommand AddCourseCommand
        {
            get;
            private set;
        }
        public void AddNewTab()
        {
            NewCourseName ncn = new NewCourseName();
            ncn.ShowDialog();
            if (ncn.courseName != null)
            {
                MyHomeworkModel newTab = new MyHomeworkModel();
                newTab.Header = ncn.courseName;
                newTab.Text = ncn.courseName;
                AllTabs.Add(newTab);
                SelectedTab = newTab;
            }
        }
        private void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

编辑:刚刚注意到我收到了这条消息:

System.Windows.Data Error: 40 : BindingExpression path error: 'Text' property not found on 'object' ''MyHomeworkViewModel' (HashCode=31265986)'. BindingExpression:Path=Text; DataItem='MyHomeworkViewModel' (HashCode=31265986); target element is 'TextBox' (Name=''); target property is 'Text' (type 'String')

我想我知道它为什么抱怨了。我的文本属性是MyHomeworkModel而不是MyHomeworkViewModel…但是为什么我在MyHomeworkModel中将header绑定到header属性呢?

我的AddCourseCommand类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace MyHomework__MVVM_
{
    class AddCourseCommand : ICommand
    {
        private MyHomeworkViewModel viewModel;
        public AddCourseCommand(MyHomeworkViewModel viewModel)
        {
            this.viewModel = viewModel;
        }
        public event EventHandler CanExecuteChanged
        {
            add
            {
                CommandManager.RequerySuggested += value;
            }
            remove
            {
                CommandManager.RequerySuggested -= value;
            }
        }
        public bool CanExecute(object parameter)
        {
            return true;
        }
        public void Execute(object parameter)
        {
            viewModel.AddNewTab();
        }
    }
}

为什么这些选项卡似乎共享同一个文本框?

似乎你的模型实现

ObservableCollection<MyHomeworkModel>.

删除这个基类,它应该可以工作。

编辑:

您需要更改:

       AddCourseCommand = new AddCourseCommand(this);

下载DelegateCommand

       AddCourseCommand = new DelegateCommand(AddNewTab);
编辑:

你从你的UI中剪切你的ViewModel。你复制一个实例到你的命令中,然后调用那个Copy add。这是错误的,属性是你的错。我真的建议你使用DelegateCommand,这可能会修复它。

To your guess:

我想我知道为什么它在抱怨。我的文本属性是MyHomeworkModel而不是MyHomeworkViewModel…但是为什么我在MyHomeworkModel中将header绑定到header属性呢?

这是正确的,你的属性是在MyHomeworkModel,而不是在MyHomeworkViewModel,你绑定到一个包含MyHomeworkModel s的列表。现在你添加一个新项目,你的绑定将设置在最底层。在这种情况下,在MyHomeworkModel的实例中,而不是在MyHomeworkViewModel