我正在开发一个用于学习目的的小型应用程序。我发现当我将ItemControl的ItemSource绑定到XAML中的ViewModel属性时,它并没有以预期的方式工作。即它在加载时加载带有值的底层集合,但不会反映对它的任何更改。 但是,如果我在Codebehind中设置Itemsource,它就可以工作。
加载表单时,它会显示2个注释对象。单击按钮应显示第3个。我不明白为什么使用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));
}
}
}
答案 0 :(得分:1)
您创建一个MainViewModel实例并将其分配给XAML中的MainWindow DataContext
<Window.DataContext >
<vm:MainViewModel/>
</Window.DataContext>
XAML中的绑定使用此实例作为其源对象,只要您没有明确指定其他源。因此,不需要(并且这是一个错误)在后面的代码中创建另一个实例。
更改MainWindow的构造函数,如下所示:
public MainWindow()
{
InitializeComponent();
ViewModel = (MainViewModel)DataContext;
}
答案 1 :(得分:0)
试试这个:
<Window.Resources>
<vm:MainViewModel x:Key="mainVM"/>
</Window.Resources>
&#13;
现在使用此密钥作为静态资源,无论您绑定的内容如何:
<ItemsControl Name="NoteItemControl" ItemsSource="{Binding notes,Source={StaticResource mainVM},Mode=TwoWay}" Background="Beige" >
&#13;
如果你这样做,你就不需要任何datacontext