2016-07-01 2 views
0

WPF GridView hat standardmäßig AutoGenerateColumns, dh true. Dies bewirkt, dass das GridView Header basierend auf der Klasse generiert.Generieren von GridView-Kopfzeilen automatisch von der Schnittstelle statt der Klasse

Ich möchte diese Funktion verwenden, aber WPF auf Eigenschaften in einer Schnittstelle statt der Klasse einschränken.

Im unteren Beispiel sehen Sie zwei Eigenschaften. CanBeSeen ist derjenige, der gesehen werden sollte. Other ist die Eigenschaft, die nicht Teil der Schnittstelle ist und daher ausgeblendet werden sollte.

Kann dies getan werden?

XAML:

<Window x:Class="Stackoverflow.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="auto" Width="auto"> 
    <Grid> 
     <DataGrid x:Name="Gridly" ItemsSource="{Binding GridlyItemsSource}" /> 
    </Grid> 
</Window> 

xaml.cs

using System.Collections.Generic; 
using System.Windows; 

namespace Stackoverflow 
{ 
    public interface IGridlyViewModel 
    { 
     int CanBeSeen { get; } 
    } 

    public class ModelData :IGridlyViewModel 
    { 
     #region IGridlyViewModel 
     public int CanBeSeen { get { return 42; } } 
     #endregion 
     public int Other { get { return 9001; } } 
    } 

    public partial class MainWindow : Window 
    { 

     public IEnumerable<IGridlyViewModel> GridlyItemsSource { get { return new[] { new ModelData() }; } } 

     public MainWindow() 
     { 
      this.DataContext = this; 
      InitializeComponent(); 
     } 
    } 
} 

Ausgang:

DataGrid Output

+1

Ja, das ist möglich. Sie können eine AttachedProperty/Behavior für diese spezifizierende Schnittstelle als Eingabe schreiben und reflection verwenden. Ich werde das heute tun. Interessant! – AnjumSKhan

Antwort

1

Ich habe gelöst Ihr Problem mit Attached Properties und AutoGeneratingColumn Fall DataGrid.

Im folgenden Beispiel ist WinGrd mein Hauptfenster, und ich habe alles darin behalten. Sie können einfach alles einfügen.

Verbrauch:

<DataGrid local:WinGrd.FilteringInterface="{x:Type local:IGridlyViewModel}" 
      local:WinGrd.ViewModel="{x:Type local:ModelData}" 
      ItemsSource="{Binding GridlyItemsSource}" /> 

Code:

namespace WpfBinding.Interface 
{ 
    /// <summary> 
    /// Interaction logic for WinGrd.xaml 
    /// </summary> 
    public partial class WinGrd : Window 
    { 
     public IEnumerable<IGridlyViewModel> GridlyItemsSource { get { return new[] { new ModelData() }; } } 

     public WinGrd() 
     { 
      InitializeComponent(); 

      this.DataContext = this; 
     } 

     #region FilteringInterface 

     public static Type GetFilteringInterface(DependencyObject obj) 
     { 
      return (Type)obj.GetValue(FilteringInterfaceProperty); 
     } 

     public static void SetFilteringInterface(DependencyObject obj, Type value) 
     { 
      obj.SetValue(FilteringInterfaceProperty, value); 
     } 

     // Using a DependencyProperty as the backing store for FilteringInterface. This enables animation, styling, binding, etc... 
     public static readonly DependencyProperty FilteringInterfaceProperty = 
      DependencyProperty.RegisterAttached("FilteringInterface", typeof(Type), typeof(WinGrd), 
         new PropertyMetadata(new PropertyChangedCallback(FilteringInterfaceChanged))); 

     private static void FilteringInterfaceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
     { 
      DataGrid dGrid = (DataGrid)d; 
      dGrid.AutoGeneratingColumn += dGrid_AutoGeneratingColumn; 
     }    

     #endregion 

     #region ViewModel AttachedProperty 

     public static Type GetViewModel(DependencyObject obj) 
     { 
      return (Type)obj.GetValue(ViewModelProperty); 
     } 

     public static void SetViewModel(DependencyObject obj, Type value) 
     { 
      obj.SetValue(ViewModelProperty, value); 
     } 

     // Using a DependencyProperty as the backing store for ViewModel. This enables animation, styling, binding, etc... 
     public static readonly DependencyProperty ViewModelProperty = 
      DependencyProperty.RegisterAttached("ViewModel", typeof(Type), typeof(WinGrd), new PropertyMetadata(null));     

     #endregion 

     static void dGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e) 
     { 
      DataGrid dGrid = (DataGrid)sender; 

      TypeInfo viewModelTypeInfo = WinGrd.GetViewModel(dGrid).GetTypeInfo(); 
      Type[] allInterfaces = viewModelTypeInfo.GetInterfaces(); 

      Type foundInterface = allInterfaces.FirstOrDefault((tp) => { return tp == WinGrd.GetFilteringInterface(dGrid); }); 

      if (foundInterface == null) 
       return; 

      TypeInfo foundInterfaceTypeInfo = foundInterface.GetTypeInfo(); 
      PropertyInfo[] foundInterfaceProps = foundInterfaceTypeInfo.GetProperties(); 

      if (foundInterfaceProps.FirstOrDefault((p) => { return p.Name == e.PropertyName; }) != null) 
       System.Diagnostics.Debug.WriteLine(e.PropertyName + " found and used for Column !"); 
      else 
       e.Cancel = true; 
     } 

    } 

    #region Classes 

    public interface IGridlyViewModel 
    { 
     int CanBeSeen { get; } 
    } 

    public class ModelData : IGridlyViewModel 
    { 
     #region IGridlyViewModel 
     public int CanBeSeen { get { return 42; } } 
     #endregion 
     public int Other { get { return 9001; } } 
    } 

    #endregion 
} 
1

Die Antwort ist, dass Sie in Ihrem Fall kann es nicht erreichen, indem er einfach einstellen ItemsSource zu Interface-Objekt. Es ist unmöglich und Gründe dafür sind ziemlich offensichtlich. Die Funktion "AutoGenerateColumns" ist für Ihren Fall nicht geeignet. Sie können Spalten explizit angeben. Bitte beachten Sie folgende Snippet:

<DataGrid ItemsSource="{Binding GridlyItemsSource}" AutoGenerateColumns="False" > 
    <DataGrid.Columns> 
    <DataGridTextColumn Header="CanBeSeen column" Binding="{Binding CanBeSeen }" />  
    </DataGrid.Columns> 
</DataGrid>