2012-08-13 42 views
2

我有一個ListBox我綁定到視圖模型中的ObservableCollection<Series>。每次用戶點擊「刪除」按鈕DeleteDelegateCommand,在Series類中執行特定項目,並從數據庫中刪除該項目。Refresh ObservableCollection <T>當T屬性更改 - WPF MVVM

我正在尋找某種方式來更新ObservableCollection<Series>這種情況發生,以便在相關項目被刪除後立即從XAML視圖中刪除。

目前,這是不會發生的,我是比較新的WPF和一直在努力得到這個工作的日子裏,請建議我要去哪裏錯了:

相關XAML:

<ListBox ItemsSource="{Binding SeriesCollection}" Name="lbSeries" Background="#6E7587" ItemContainerStyle="{StaticResource highlightStyle}" SelectionMode="Single" AlternationCount="2" Grid.Row="2" ScrollViewer.VerticalScrollBarVisibility="Auto"> 
    <ListBox.ItemTemplate> 
     <DataTemplate> 
      <Grid> 
       <Grid.ColumnDefinitions> 
        <ColumnDefinition Width="200" /> 
        <ColumnDefinition Width="100" /> 
        <ColumnDefinition Width="100" /> 
        <ColumnDefinition Width="100" /> 
        <ColumnDefinition Width="100" /> 
        <ColumnDefinition Width="*" /> 
       </Grid.ColumnDefinitions> 
       <TextBox Margin="5,0" FontSize="14" Name="txtName" Text="{Binding Name}" Width="190" Height="30" Grid.Column="0" /> 
       <wpfToolkit:IntegerUpDown Value="{Binding Season}" Name="nudSeason" FontSize="14" Height="30" Width="95" Increment="1" Maximum="100000" Minimum="0" Grid.Column="1" /> 
       <wpfToolkit:IntegerUpDown Value="{Binding Episode}" Name="nudEpisode" FontSize="14" Height="30" Width="95" Increment="1" Maximum="100000" Minimum="0" Grid.Column="2" /> 
       <Button Command="{Binding Save}" Grid.Column="3" Width="60" Height="50" Cursor="Hand" ToolTip="Save program" VerticalAlignment="Center" HorizontalAlignment="Center"> 
        <Button.Template> 
         <ControlTemplate> 
          <Border HorizontalAlignment="Center" VerticalAlignment="Center" > 
           <Image Source="Resources\Save.png" Width="30" Height="40" /> 
          </Border> 
         </ControlTemplate> 
        </Button.Template> 
       </Button> 
       <Button Command="{Binding Delete}" Grid.Column="4" Width="60" Height="50" Cursor="Hand" CommandParameter="{Binding ElementName=lbSeries,Path=SelectedItem}" ToolTip="Remove program" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="15,0"> 
        <Button.Template> 
         <ControlTemplate> 
          <Border HorizontalAlignment="Center" VerticalAlignment="Center" > 
           <Image Source="Resources\Delete.png" Width="30" Height="40" /> 
          </Border> 
         </ControlTemplate> 
        </Button.Template> 
       </Button> 
       <Label Content="{Binding Information}" Grid.Column="5" FontSize="14" Margin="10,0" /> 
      </Grid> 
     </DataTemplate> 
    </ListBox.ItemTemplate> 
</ListBox> 

視圖模型:

using System; 
using System.Collections.ObjectModel; 
using System.ComponentModel; 
using System.Data; 
using SeriesTracker.Functions; 
using System.Linq; 

namespace SeriesTracker.Client 
{ 
    public class SeriesTrackerViewModel : INotifyPropertyChanged 
    { 
     public DelegateCommand NewSeries { get; set; } 

     public event PropertyChangedEventHandler PropertyChanged; 

     private ObservableCollection<Series> _series = new ObservableCollection<Series>(); 
     public ObservableCollection<Series> SeriesCollection 
     { 
      get { return _series; } 
      set 
      { 
       _series = value; 
       RaisePropertyChanged("SeriesCollection"); 
      } 
     } 

     public SeriesTrackerViewModel() 
     { 
      NewSeries = new DelegateCommand(AddNewSeries); 

      DataTable table = DataAccessLayer.GetSeries(); 
      if (table.Rows.Count > 0) 
       LoadSeries(table); 
     } 

     private void LoadSeries(DataTable table) 
     { 
      foreach (DataRow row in table.Rows) 
      { 
       int id = Int32.Parse(row["Id"].ToString()); 
       string name = row["Name"].ToString(); 

       int season = 0; 
       int episode = 0; 

       if (Int32.TryParse(row["Season"].ToString(), out season) && 
        Int32.TryParse(row["Episode"].ToString(), out episode)) 
       { 
        var series = new Series(id, name, season, episode); 
        SeriesCollection.Add(series); 
       } 
      } 
     } 

     public void AddNewSeries() 
     { 
      SeriesCollection.AddSeries(); 
     } 

     private void RaisePropertyChanged(string propertyName) 
     { 
      PropertyChangedEventHandler handler = PropertyChanged; 
      if (handler != null) 
       handler(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
} 

小號eries類:

using System; 
using System.ComponentModel; 
using System.Collections.ObjectModel; 

namespace SeriesTracker.Functions 
{ 
    public class Series : INotifyPropertyChanged 
    { 
     public event PropertyChangedEventHandler PropertyChanged; 

     private DelegateCommand _save; 
     public DelegateCommand Save 
     { 
      get { return _save; } 
      set 
      { 
       _save = value; 
       RaisePropertyChanged("Save"); 
      } 
     } 

     private DelegateCommand _delete; 
     public DelegateCommand Delete 
     { 
      get{return _delete;} 
      set 
      { 
       _delete = value; 
       RaisePropertyChanged("Delete"); 
      } 
     } 

     public int Id { get; set; } 

     string _name; 
     public String Name 
     { 
      get { return _name; } 
      set 
      { 
       _name = value; 
       RaisePropertyChanged("Name"); 
      } 
     } 

     int _season; 
     public Int32 Season 
     { 
      get { return _season; } 
      set 
      { 
       _season = value; 
       RaisePropertyChanged("Season"); 
      } 
     } 

     int _episode; 
     public Int32 Episode 
     { 
      get { return _episode; } 
      set 
      { 
       _episode = value; 
       RaisePropertyChanged("Episode"); 
      } 
     } 

     string _information; 
     public String Information 
     { 
      get { return _information; } 
      set 
      { 
       _information = value; 
       RaisePropertyChanged("Information"); 
      } 
     } 

     public Series(int id,string name,int season, int episode) 
     { 
      Id = id; 
      Name = name; 
      Season = season; 
      Episode = episode; 

      Save = new DelegateCommand(SaveItem); 
      Delete = new DelegateCommand(DeleteItem); 
     } 

     public void DeleteItem() 
     { 
      var selectedItem = this; 
      if (selectedItem.Id != -1) 
      { 
       DataAccessLayer.Delete(selectedItem.Id); 
      } 
     } 

     public void SaveItem() 
     { 
      var selectedItem = this; 
      if (selectedItem.Id == -1) 
       DataAccessLayer.AddEntry(selectedItem.Name,selectedItem.Season,selectedItem.Episode); 
      else 
       DataAccessLayer.Update(selectedItem.Id, 
        selectedItem.Name,selectedItem.Season,selectedItem.Episode); 
     } 

     private void RaisePropertyChanged(string propertyName) 
     { 
      PropertyChangedEventHandler handler = PropertyChanged; 
      if (handler != null) 
       handler(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
} 

回答

4

你不應該保留的DeleteCommand在系列類,它應該是在視圖模型。

而在視圖模型中,您可以輕鬆更新ObservableCollection。

您需要在ViewModel和XAML上使用類型系列的通用委託命令,您需要在命令參數上傳遞{綁定}。

視圖模型C#: -

DelegateCommand<Series> DeleteCommand { get; set; } 
DeleteCommand = new RelayCommand<Series>(OnDelete); 

// This method will gets execute on click the of Delete Button1 
private void OnDelete(Series series) 
{ 
} 

XAML: - 刪除按鈕改變結合和命令參數值

CommandParameter = 「{結合}」
命令=「{Binding DataContext.DeleteCommand,RelativeSource = {RelativeSource Mode = FindAncestor,AncestorType = {x:Type Window}}}」

希望這將幫助你

+2

我同意。將命令移動到視圖模型並將Series實例作爲命令參數傳入。刪除數據庫中的系列,然後從ObservableCollection中刪除相同的系列。從可觀察集合中刪除該項目將導致視圖更新。 – 2012-08-13 15:07:48

+0

如果我將DeleteCommand移動到視圖模型,我將如何知道用戶正在刪除哪個項目?因爲當他們單擊ListBox中的Delete按鈕時,沒有選擇按鈕被點擊的行。我已經嘗試了這種方法,並回到了系列calss中的刪除命令,因爲我只需在點擊事件 – 2012-08-14 06:06:42

+0

中指定'this'就可以訪問點擊的項目,請參閱更新的註釋,它將解決您的問題。 – pchajer 2012-08-14 09:29:50

1

您可以訂閱各系列的PropertyChangedEventHandlerObservableCollection,然後調用RaisePropertyChanged("SeriesCollection")時觸發的事件

更新:我的意思是類似的東西:

private void LoadSeries(DataTable table) 
{ 
    ... 
    { 
     var series = new Series(id, name, season, episode); 
     series.PropertyChanged += { RaisePropertyChanged("SeriesCollection"); } 
     SeriesCollection.Add(series); 
    } 
}  
+0

RaisePropertyChanged(「SeriesCollection」)只有在視圖模型中運行它時才起作用,它在Series類中不起作用,因爲SeriesCollection是在視圖模型中定義的 – 2012-08-14 06:08:23

+0

我知道它,我添加了代碼。但我認爲pchajer的答案是一個更清晰的變體 – kotlyarovsa 2012-08-14 09:47:32

相關問題