使用 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" >
如果你这样做,你不需要任何数据上下文
我正在开发一个用于学习目的的小应用程序。我发现当我将 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" >
如果你这样做,你不需要任何数据上下文