2015-10-06 2 views
0

В пользовательском элементе управления ListView я создаю маленькую кнопку «Экспорт в Excel», которая отправляет все содержимое ListView в Excel. Поскольку эта кнопка встроена в элемент управления ListView, я не знаю, какой объект указан или какие столбцы показаны.Как временно отключить виртуализацию виртуализации WPF?

Так что мой метод является общим и просто анализирует все заголовки столбцов и все строки для экспорта данных в Excel. Но при анализе ListViewItem, которые не видны, вы получаете нулевой результат. Решением было бы установить VirtualizingStackPanel.VirtualizationMode = «False» в моем ListView, но это сильно повлияло на опыт графического интерфейса пользователя, когда у вас есть тысячи строк.

Я ищу способ загрузить весь ListViewItem только для моих общих методов экспорта и сохранить виртуализацию для графического интерфейса.

Может ли кто-нибудь помочь мне в этом?

спасибо.

+0

Я не понимаю, что вы хотите, единственный способ отключить виртуализацию установлен 'VirtualizingStackPanel .IsVirtualizingProperty' - false. Вы можете включить его снова после завершения вашего метода. – Hopeless

+1

Вы должны просто использовать базовые данные для своей задачи, а не созданные контейнеры пользовательского интерфейса. – metacircle

+0

Данные Uderlying - это данные таблиц из базы данных SQL, которые как много больше полей, которые я показываю в столбце (даже связанная таблица). В моем приложении много ListView, это означало бы, что мне нужно будет вернуться в каждом представлении и определить, что должно быть экспортировано в Excel или нет. Поэтому я ищу способ заставить ListView загружать все элементы по коду. – Karnalta

ответ

0

Я, наконец, пришел, чтобы решить мою проблему. В принципе, я сначала разобрал весь столбец, чтобы найти имя связанного свойства. Затем сделайте некоторое отражение в коллекции Items из ListView, чтобы найти значение свойства.

Вот код (еще не полированная):

private void OnExportToExcel(object sender, ExecutedRoutedEventArgs args) 
    { 
     if (this.Items.Count > 0) 
     { 
      // Ensure we have a visible and selected item 
      if (this.SelectedItem == null) 
       this.SelectedItem = this.Items[0]; 
      this.ScrollIntoView(this.SelectedItem); 

      // Allow UI thread to update first or our selected lvi will be null if not visible 
      UIHelpers.AllowUIToUpdate(); 

      List<string> columnPropertyBindingPathList = new List<string>(); 
      int colIndex = 0; 

      // Get column binding path of underlying data 
      foreach (GridViewColumn h in ((GridView)this.View).Columns) 
      { 
       string bindingPath = ""; 

       if (h.DisplayMemberBinding != null) 
       { 
        bindingPath = (h.DisplayMemberBinding as Binding).Path.Path; 
       } 
       else 
       { 
        ListViewItem lvi = this.ItemContainerGenerator.ContainerFromIndex(this.SelectedIndex) as ListViewItem; 
        if (lvi != null) 
        { 
         GridViewRowPresenter gvp = UIHelpers.FindVisualChild<GridViewRowPresenter>(lvi); 
         DependencyObject col = VisualTreeHelper.GetChild(gvp, colIndex); 
         TextBlock tb = col as TextBlock; 
         if (tb == null) 
         { 
          tb = UIHelpers.FindVisualChild<TextBlock>(col); 
          bindingPath = BindingOperations.GetBinding(tb, TextBlock.TextProperty).Path.Path; 
         } 
        } 
       } 

       colIndex++; 
       if (bindingPath != "") 
        columnPropertyBindingPathList.Add(bindingPath); 
      } 

      if (columnPropertyBindingPathList.Count > 0) 
      { 
       Mouse.SetCursor(Cursors.Wait); 

       // Init array to export to excel 
       object[,] dataArray = new object[this.Items.Count + 1, columnPropertyBindingPathList.Count]; 

       // Add column header 
       for (int colCnt = 0; colCnt < columnPropertyBindingPathList.Count; colCnt++) 
        dataArray[0, colCnt] = columnPropertyBindingPathList[colCnt]; 

       // Reflection to read underlying objects 
       int rowCnt = 1; 
       foreach (object obj in this.Items) 
       { 
        for (int colCnt = 0; colCnt < columnPropertyBindingPathList.Count; colCnt++) 
         dataArray[rowCnt, colCnt] = UIHelpers.GetPropValue(columnPropertyBindingPathList[colCnt], obj); 

        rowCnt++; 
       } 

       Mouse.SetCursor(Cursors.Arrow); 

       // Throw event 
       RoutedEventArgs newEventArgs = new RoutedEventArgs(EmListView.ExportToExcelEvent); 
       newEventArgs.Source = dataArray; 
       RaiseEvent(newEventArgs); 
      } 
      else 
      { 
       // Throw event 
       RoutedEventArgs newEventArgs = new RoutedEventArgs(EmListView.ExportToExcelEvent); 
       newEventArgs.Source = null; 
       RaiseEvent(newEventArgs); 
      } 
     } 
     else 
     { 
      // Throw event 
      RoutedEventArgs newEventArgs = new RoutedEventArgs(EmListView.ExportToExcelEvent); 
      newEventArgs.Source = null; 
      RaiseEvent(newEventArgs); 
     } 
    } 

UIHelpers методы:

/// <summary> 
    /// Give the UI thread the time to refresh 
    /// </summary> 
    public static void AllowUIToUpdate() 
    { 
     DispatcherFrame frame = new DispatcherFrame(); 

     Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Render, new DispatcherOperationCallback(delegate(object parameter) 
     { 
      frame.Continue = false; 
      return null; 
     }), null); 

     Dispatcher.PushFrame(frame); 
    } 

    /// <summary> 
    /// Find a visual child type inside a DependencyObject 
    /// </summary> 
    /// <typeparam name="T"></typeparam> 
    /// <param name="obj"></param> 
    /// <returns></returns> 
    public static T FindVisualChild<T>(DependencyObject obj) where T : DependencyObject 
    { 
     for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++) 
     { 
      DependencyObject child = VisualTreeHelper.GetChild(obj, i); 
      if (child != null && child is T) 
       return (T)child; 
      else 
      { 
       T childOfChild = FindVisualChild<T>(child); 
       if (childOfChild != null) 
        return childOfChild; 
      } 
     } 
     return null; 
    } 

    /// <summary> 
    /// Find a property value inside a object (even for multi level property) 
    /// </summary> 
    /// <param name="name"></param> 
    /// <param name="obj"></param> 
    /// <returns></returns> 
    public static Object GetPropValue(String name, Object obj) 
    { 
     foreach (String part in name.Split('.')) 
     { 
      if (obj == null) { return null; } 

      Type type = obj.GetType(); 
      PropertyInfo info = type.GetProperty(part); 

      if (info == null) { return null; } 

      obj = info.GetValue(obj, null); 
     } 

     return obj; 
    } 
Смежные вопросы