2009-04-02 7 views
8

Il DataTemplate predefinito in un'applicazione wpf visualizza il risultato del metodo .ToString(). Sto sviluppando un'applicazione in cui il DataTemplate predefinito non dovrebbe visualizzare nulla.Specificare un DataTemplate vuoto predefinito anziché il valore predefinito 'ToString()' DataTemplate

ho provato:

<Grid.Resources> 
    <DataTemplate DataType="{x:Type System:Object}"> 
    <Grid></Grid> 
    </DataTemplate> 
</Grid.Resources> 

Ma questo non funziona. Qualcuno sa se questo è possibile senza specificare un DataTemplate specifico per ogni tipo di classe nell'applicazione?

risposta

4

Non so come farlo. Come da commento di Joe di seguito, WPF non consente specificamente di specificare un DataTemplate per il tipo Object.

A seconda dei requisiti specifici, potrebbe essere più semplice cercare uno DataTemplate corrispondente al tipo specifico. Se ne trovi uno, usalo. Altrimenti, non visualizzare nulla. Per esempio:

<ContentControl Content="{Binding YourContent}" ContentTemplateSelector="{StaticResource MyContentTemplateSelector}"/> 

E nel selettore (pseudo-codice, ovviamente):

var dataTemplateKey = new DataTemplateKey() { DataType = theType; }; 
var dataTemplate = yourControl.FindResource(dataTemplateKey); 

if (dataTemplate != null) 
{ 
    return dataTemplate; 
} 

return NulloDataTemplate; 
+2

"WPF corrisponde a un oggetto con la sua DataTemplate da esatto tipo di runtime" - Non è vero. Se si aggiunge un DataTemplate con DataType = BaseClass, corrisponderà anche alla sottoclass. L'ho visto funzionare. Sfortunatamente, il framework non consente in modo specifico di creare un DataTemplate per System.Object; si ottiene un errore di runtime "La costruzione del tipo" DataTemplateKey "non è riuscita. DataTemplate.DataType non può essere di tipo Object." –

+0

Hai ragione. Stavo pensando agli stili, che non vengono automaticamente ereditati. Aggiornamento della mia risposta. Grazie. –

1

io non sono sicuro di sostituire il default DataTemplate, ma è possibile utilizzare un ValueConverter per passare visualizzazione ToString nel caso di determinati tipi e una stringa vuota altrimenti. Ecco po 'di codice (si noti che il doesnt TypeB blocco di testo ha il convertitore sopra per vedere che cosa assomiglia normalmente):

XAML:

<Window x:Class="EmptyTemplate.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:loc="clr-namespace:EmptyTemplate" 
    Title="Window1" Height="300" Width="300"> 
    <Window.Resources> 
     <loc:AType x:Key="atype"/> 
     <loc:BType x:Key="btype"/> 
     <loc:TypeConverter x:Key="TypeConverter"/> 
    </Window.Resources> 
    <StackPanel> 
     <Button Content="{Binding Source={StaticResource atype}, Converter={StaticResource TypeConverter}}"/> 
     <Button Content="{Binding Source={StaticResource btype}, Converter={StaticResource TypeConverter}}"/> 
     <TextBlock Text="{Binding Source={StaticResource atype}, Converter={StaticResource TypeConverter}}"/> 
     <TextBlock Text="{Binding Source={StaticResource btype}}"/> 
    </StackPanel> 
</Window> 

.xaml.cs:

namespace EmptyTemplate 
{ 
    /// <summary> 
    /// Interaction logic for Window1.xaml 
    /// </summary> 
    public partial class Window1 : Window 
    { 
     public Window1() 
     { 
      InitializeComponent(); 
     } 
    } 

    public class AType { } 

    public class BType { } 

    public class TypeConverter : IValueConverter 
    { 
     public DataTemplate DefaultTemplate { get; set; } 

     #region IValueConverter Members 

     public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
     { 
      if (value.GetType() == typeof(AType)) 
      { 
       return value.ToString(); 
      } 
      return DefaultTemplate; 
     } 

     public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
     { 
      throw new NotImplementedException(); 
     } 

     #endregion 
    } 
} 
4

Se si utilizza lo schema MVVM e si dispone di una classe astratta derivata da tutte le classi ViewModel, è possibile utilizzare tale classe anziché System.Object:

<Grid.Resources> 
    <DataTemplate DataType="{x:Type vm:VMBase}"> 
    </DataTemplate> 
</Grid.Resources> 
+2

Mi hai appena salvato la vita. Beh, non letteralmente ovviamente, ma questo è esattamente quello che stavo cercando – Firedragon

2

Ho usato Nullable, ho lavorato per la mia situazione.

<DataTemplate DataType="{x:Type sys:Nullable}"> 
<!-- Content --> 
</DataTemplate> 
0

Ecco un esempio di lavoro su come effettuare questa operazione utilizzando un selettore (il modo migliore IMO):

public class EmptyDefaultDataTemplateSelector : DataTemplateSelector 
{ 
    public override DataTemplate SelectTemplate(object item, DependencyObject container) 
    { 
     if (item != null) 
     { 
      var dataTemplateKey = new DataTemplateKey(item.GetType()); 
      var dataTemplate = ((FrameworkElement) container).TryFindResource(dataTemplateKey); 
      if (dataTemplate != null) 
       return (DataTemplate) dataTemplate; 
     } 

     return new DataTemplate(); //null does not work 
    } 
}