2017-09-04 55 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没有更新,或者为什么应用程序总体上表现得很奇怪。 –