2017-09-04 52 views
0

這裏可能有一些解決方案,但到目前爲止,我找不到解決方案。任何幫助,將不勝感激。目前我有一個對話框,我可以通過單擊按鈕或從文件資源管理器拖放文件來上傳文件。該對話框包含一個DataGrid,綁定到ObservableCollection<FileDetails>PropertyChanged的事件處理程序也已附加到此屬性。當我通過按鈕添加一個文件時,會觸發PropertyChanged事件,並使用添加的文件更新UI。但是,當我將文件拖放到dataGrid時,PropertyChanged處理程序爲空。PropertyChanged在拖放時爲空

下面是我的ViewModel:

public class FileUploadVM : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 
    private static ObservableCollection<FileDetails> m_DialogFiles; 
    public ObservableCollection<FileDetails> DialogFiles 
    { 
     get 
     { 
      return m_DialogFiles ?? new ObservableCollection<FileDetails>(); 
     } 
     set 
     { 
      m_DialogFiles = value; 
      this.NotifyPropertyChanged(nameof(DialogFiles)); 
     } 
    } 

    public ICommand FileUpload 
    { 
     get 
     { 
      return new SimpleCommand(AddFiles); 
     } 
    } 

    private void AddFiles(object obj) 
    { 
     OpenFileDialog openFile = new OpenFileDialog(); 
     openFile.Multiselect = true; 
     if (openFile.ShowDialog() == true) 
     { 
      m_fileList = openFile.FileNames.ToList(); 
      GetFileWithIcon(); 
     } 
     DialogFiles = new ObservableCollection<FileDetails>(dgFiles); 
    } 
} 

下面是我的XAML代碼

<Grid ShowGridLines="False"> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="Auto"/> 
     <RowDefinition /> 
    </Grid.RowDefinitions> 
    <DataGrid x:Name="dataGrid1" Height="100" ItemsSource="{Binding Path=DialogFiles, UpdateSourceTrigger=PropertyChanged}" CanUserAddRows="False" AutoGenerateColumns="False" 
       GridLinesVisibility="None" CanUserDeleteRows="True" HeadersVisibility="None" AllowDrop="True" Drop="dataGrid1_Drop"> 
     <DataGrid.Columns> 
      <DataGridTemplateColumn> 
       <DataGridTemplateColumn.CellTemplate> 
        <DataTemplate> 
         <Image Source="{Binding FileIcon}" Height="20" Width="20"/> 
        </DataTemplate> 
       </DataGridTemplateColumn.CellTemplate> 
      </DataGridTemplateColumn> 
      <DataGridTextColumn Binding="{Binding FileName}" Width="Auto"></DataGridTextColumn> 
      <DataGridTemplateColumn Width="Auto"> 
       <DataGridTemplateColumn.CellTemplate> 
        <DataTemplate> 
         <Button Command="Delete"> 
          <Image Source="/AssemblyName;component/Resources/delete_icon.png" Height="15" Width="20"/> 
         </Button> 
        </DataTemplate> 
       </DataGridTemplateColumn.CellTemplate> 
      </DataGridTemplateColumn> 
     </DataGrid.Columns> 
    </DataGrid> 
    <StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Right"> 
     <Button Width="60" Margin="10" Command="{Binding Path=FileUpload}">Add Files</Button> 
     <Button Width="60" Margin="10">Upload</Button> 
    </StackPanel> 
</Grid> 

一個組成部分,這是代碼隱藏

public partial class FileDialog : Window 
{ 
    private ObservableCollection<FileDetails> m_fileDialog; 
    public FileDialog() 
    { 
     InitializeComponent(); 
     this.DataContext = FileUpload; 
    } 

    public FileUploadVM FileUpload 
    { 
     get 
     { 
      return new FileUploadVM(); 
     } 
    } 

    public ObservableCollection<FileDetails> DialogFiles 
    { 
     get 
     { 
      return m_fileDialog ?? FileUpload.DialogFiles; 
     } 
    } 

    private void dataGrid1_Drop(object sender, DragEventArgs e) 
    { 
     string[] droppedFiles = null; 
     if (e.Data.GetDataPresent(DataFormats.FileDrop)) 
     { 
      droppedFiles = e.Data.GetData(DataFormats.FileDrop, true) as string[]; 
     } 
     if ((null == droppedFiles) || (!droppedFiles.Any())) 
     { 
      return; 
     } 
     foreach (var item in droppedFiles) 
     { 
      FileUploadVM.m_fileList.Add(item); 
     }    
     FileUpload.GetFileWithIcon(); 
     FileUpload.DialogFiles = new ObservableCollection<FileDetails>(FileUploadVM.dgFiles); 
     FileUploadVM.m_fileList.Clear(); 
    } 
} 

如上點擊AddFiles作品提到不錯,但拖放不會觸發PropertyChanged,儘管DialogFiles內有值。

+3

property'FileUpload'在每次調用*時創建一個新的intance *。你使用多個實例而不是1 – ASh

+0

請看下面的答案,你不需要在該屬性上觸發NotifyChange,因爲它是一個ObservableCollection。當添加/刪除/清除該集合時,它會自動通知視圖該集合已更改,所以你不應該擔心:) –

+0

@ASh謝謝!我不能相信我忽略了這一點。 – Akshatha

回答

1

Akshatha

我已經發現了一些問題,與您的解決方案:

問題1 - 您可以設置您的DataContext(視圖模型)不正確,如果你看一下下面的代碼:

public FileUploadVM FileUpload { 
    get { 
     return new FileUploadVM(); 
    } 
} 

上面的代碼每次請求ViewModel對象時都會創建一個ViewModel的新實例。這意味着,當你調用這個對象:

FileUploadVM.m_fileList.Clear(); 

它會創建一個新的對象,並會破壞你的參考你的DataContext(查看 - >視圖模型)。

private FileUploadVM fileUploadVM = new FileUploadVM(); 

public FileUploadVM FileUploadVM { 
    get { return this.fileUploadVM; } 
    set { 
     if (this.fileUploadVM != value) { 
      this.fileUploadVM = value; 
     } 
    } 
} 

問題2

編輯 你可以通過創建一個正常的屬性檢索視圖模型對象,並使用該實例每次您需要訪問您的視圖模型的時間解決這個問題你消滅你當您重新初始化您的DialogFiles集合時參考:

FileUploadVM.DialogFiles = new ObservableCollection<FileDetails>(FileUploadVM.dgFiles); 

每當您創建此實例時對象,您的視圖將需要通知有一個新的集合需要綁定,而不要使用您不再使用的「舊」集合。一種方法,以確保您總是使用集合的正確實例是使其只讀:

public ObservableCollection<FileDetails> DialogFiles { 
    get { 
     return m_DialogFiles; 
    } 
} 

,只有加入/清除從單一實例的集合,所以不是做這樣的:

FileUploadVM.DialogFiles = new ObservableCollection<FileDetails>(FileUploadVM.dgFiles); 

的只讀媒體資源相關聯不會讓你做到這一點,而不是用它來修改你的收藏:

FileUploadVM.DialogFiles.Add(new FileDetails("Your FileName")); 

,如果你要dlete /清除收集的物品,你可以簡單地使用

FileUploadVM.DialogFiles.Clear(); 
// OR 
FileUploadVM.DialogFiles.Remove(myFileDetailsItem); 
// OR 
FileUploadVM.DialogFiles.RemoveAt(index); 

總之,你的問題是你打的投遞方法時創建了DialogFiles收集的新實例:

FileUploadVM.DialogFiles = new ObservableCollection<FileDetails>(FileUploadVM.dgFiles); 

,你應該寧願只是添加到集合不是重新聲明實例:

foreach(var file in FileUploadVM.dgFiles) { 
    FileUploadVM.DialogFiles.Add(file); 
} 
+0

謝謝你的回答。您的問題1的解決方案確實幫助我,並在那裏工作。但是,根據您的評論,如果INotifyPropertyChanged被刪除,它不會更新用戶界面。另外,我嘗試將項目添加到收藏中,但由於某些未知原因,即使在添加項目後我的收藏數量仍然爲0.這就是爲什麼我必須採用此路線。它的工作原理! – Akshatha

+0

儘管如此,你提到的是有道理的。所以接受你的答案.. – Akshatha

+1

沒問題,很高興能夠幫助。在使用MVVM模式開發WPF應用程序時,它幾乎必須使用[Snoop](https://snoopwpf.codeplex.com/)在運行時檢查應用程序的「骨架」。它爲我省去了很多煩惱,這些令人頭疼的問題是爲什麼DataContext工作不正常,爲什麼ItemsSource沒有更新,或者爲什麼應用程序總體上表現得很奇怪。 –