2009-04-02 26 views
8

Domyślny DataTemplate w aplikacji wpf wyświetla wynik metody .ToString(). Zajmuję się tworzeniem aplikacji, w której domyślny DataTemplate nie powinien wyświetlać nic.Określ domyślny pusty DataTemplate zamiast domyślnego "ToString()" DataTemplate

Próbowałem:

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

Ale to nie działa. Czy ktoś wie, czy jest to możliwe bez określania konkretnego DataTemplate dla każdego typu klasy w aplikacji?

Odpowiedz

4

Nie wiem, jak to zrobić. Zgodnie z komentarzem zamieszczonym przez Joe poniżej, WPF w szczególności uniemożliwia podanie DataTemplate dla typu Object.

W zależności od Twoich wymagań może być łatwiejsze wyszukiwanie DataTemplate pasującej do określonego typu. Jeśli znajdziesz, użyj go. W przeciwnym razie nic nie wyświetlaj. Na przykład:

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

I w wybieraka (pseudo-kod, oczywiście):

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

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

return NulloDataTemplate; 
+2

„WPF mecze obiekt z jego DataTemplate przez dokładnego typu wykonawczego” - Nieprawda. Jeśli dodasz DataTemplate z DataType = BaseClass, dopasuje on również SubClass. Widziałem, jak to działa. Niestety, framework wyraźnie uniemożliwia tworzenie DataTemplate dla System.Object; pojawia się błąd środowiska wykonawczego "Konstrukcja typu" DataTemplateKey "nie powiodła się. DataTemplate.DataType nie może być typu Object." –

+0

Masz rację. Myślałem o stylach, które nie są automatycznie dziedziczone. Aktualizuję moją odpowiedź. Dzięki. –

1

nie jestem pewien o zastąpienie domyślnego DataTemplate, ale można użyć ValueConverter przekazać wyświetlania ToString w przypadku niektórych typów i pusty ciąg w przeciwnym przypadku. Oto niektóre kodu (należy pamiętać, że nie robi TypeB TextBlock mieć przetwornicę na to, aby pokazać, jak to wygląda normalnie):

.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

Jeśli używasz wzorca MVVM i masz abstrakcyjną klasę, z której wywodzą się wszystkie klasy programu ViewModel, możesz użyć tej klasy zamiast System.Object:

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

Właśnie uratowałeś moje życie. Cóż, oczywiście nie dosłownie, ale tego właśnie szukałem – Firedragon

2

Użyłem Nullable, pracował dla mojej sytuacji.

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

Oto przykład roboczych o tym, jak to zrobić za pomocą selektora (najlepszy sposób 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 
    } 
}