2015-12-23 82 views
0

我正在開發一個用於學習目的的小應用程序。我發現當我將ItemControl的ItemSource綁定到XAML中的ViewModel屬性時,它不能以預期的方式工作。即它在加載時用值加載底層集合,但是對它的任何改變都沒有被反映出來。 但是,如果我在Codebehind中設置Itemsource,它將起作用。wpf使用XAML不起作用的數據綁定

當窗體加載時,它顯示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> 

查看代碼behind-

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")); 
     } 
    } 
} 

視圖模型 -

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)); 
     } 
    } 
} 

回答

1

您創建一個MainViewModel實例,並將其分配給主窗口的DataContext在XAML中

<Window.DataContext > 
    <vm:MainViewModel/> 
</Window.DataContext> 

只要您沒有明確指定其他來源,XAML中的綁定就會將此實例用作其源對象。所以沒有必要(也是一個錯誤)在後面的代碼中創建另一個實例。

更改主窗口的構造是這樣的:

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

試試這個:

:無論你綁定類似

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

現在使用該密鑰爲靜態資源

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

如果你這樣做,你不需要任何的datacontext