使用 XAML 的 wpf 数据绑定不起作用

wpf Databinding using XAML not working

我正在开发一个用于学习目的的小应用程序。我发现当我将 ItemControl 的 ItemSource 绑定到 XAML 中的 ViewModel 属性 时,它无法以预期的方式工作。即它在加载时加载带有值的基础集合,但不会反映对其的任何更改。 但是,如果我在 Codebehind 中设置 Itemsource,它会起作用。

加载表单时,它会显示 2 个注释对象。单击按钮应显示第三个。我不明白为什么使用 XAML 设置 DataContext 不会更新到集合中的更改。我在这里分享代码片段。非常感谢任何帮助。

XAML 的精简版 -

<Window x:Class="NotesApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:NotesApp"
        xmlns:vm="clr-namespace:NotesApp.ViewModel"
        Title="MainWindow" Height="480" Width="640">
    <Window.DataContext >
        <vm:MainViewModel/>
    </Window.DataContext>
    <DockPanel >
        <ScrollViewer VerticalScrollBarVisibility="Auto">
            <ItemsControl Name="NoteItemControl" ItemsSource="{Binding notes}" Background="Beige" >
                <ItemsControl.LayoutTransform>
                    <ScaleTransform ScaleX="{Binding Value, ElementName=zoomSlider}" ScaleY="{Binding Value, ElementName=zoomSlider}" />
                </ItemsControl.LayoutTransform>
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <Border Name="NoteBorder" Background="Green" CornerRadius="3" Margin="5,3,5,3">
                            <Grid>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition/>
                                </Grid.ColumnDefinitions>
                                <Grid.RowDefinitions>
                                    <RowDefinition/>
                                    <RowDefinition/>
                                </Grid.RowDefinitions>
                                <TextBlock Text="{Binding noteText}" Margin="5,3,5,3"/>
                                <StackPanel Grid.Row="1" Orientation="Vertical" >
                                    <Line X1="0" Y1="0" X2="{Binding ActualWidth,ElementName=NoteBorder}" Y2="0" Stroke="Black" StrokeThickness="1"/>
                                    <TextBlock Text="{Binding Category}" Margin="5,3,5,3"/>
                                </StackPanel>
                            </Grid>
                        </Border>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </ScrollViewer>
    </DockPanel>
</Window>

查看后面的代码-

namespace NotesApp
{
    public partial class MainWindow : Window
    {
        MainViewModel ViewModel { get; set; }
        public MainWindow()
        {
            InitializeComponent();
            ViewModel = new MainViewModel();
         //  IT WORKS IF I BRING IN THIS STATEMENT 
            //NoteItemControl.ItemsSource = ViewModel.notes;
        }
        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            ViewModel.AddNote(new Note("note3", "Category 3"));
        }
    }
}

ViewModel -

namespace NotesApp.ViewModel
{ 
    public class MainViewModel: INotifyPropertyChanged
    {
        ObservableCollection<Note> _notes;
        public ObservableCollection<Note> notes 
        {
            get
            { return _notes; }
            set
            {
                _notes = value;
                OnPropertyChanged("notes");
            }
        }
        public void AddNote(Note note)
        {
            _notes.Add(note);
            OnPropertyChanged("notes");
        }
        public MainViewModel ()
        {
            notes = new ObservableCollection<Note>();
            notes.Add(new Note("note1", "Category 1"));
            notes.Add(new Note("note2", "Category 2"));
        }

        public event PropertyChangedEventHandler PropertyChanged = delegate { };
        protected virtual void OnPropertyChanged(string propertyName = null)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) 
                handler(this, new PropertyChangedEventArgs( propertyName));
        }
    }
}

您创建一个 MainViewModel 实例并将其分配给 XAML

中 MainWindow 的 DataContext
<Window.DataContext >
    <vm:MainViewModel/>
</Window.DataContext>

您 XAML 中的绑定使用此实例作为它们的源对象,只要您没有明确指定其他来源。所以没有必要(这是一个错误)在代码隐藏中创建另一个实例。

像这样更改 MainWindow 的构造函数:

public MainWindow()
{
    InitializeComponent();
    ViewModel = (MainViewModel)DataContext;
}

试试这个:

<Window.Resources>
        <vm:MainViewModel x:Key="mainVM"/>
</Window.Resources>

现在,无论您在哪里绑定,都可以将此密钥用作静态资源:

<ItemsControl Name="NoteItemControl" ItemsSource="{Binding notes,Source={StaticResource mainVM},Mode=TwoWay}" Background="Beige" >
                

如果你这样做,你不需要任何数据上下文