views:

1133

answers:

2

Hi,

The default DataTemplate in a wpf application displays the result of the .ToString() method. I'm developing an application where the default DataTemplate should display nothing.

I've tried:

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

But this doesn't work. Does anyone knows if this is possible without specifiing a specific DataTemplate for every class type in the application?

Thanks

+1  A: 

I know of no way to do this. As per Joe's comment below, WPF specifically disallows specifying a DataTemplate for type Object.

Depending on your exact requirements, it may be easier to search for a DataTemplate that matches the specific type. If you find one, use it. Otherwise, display nothing. For example:

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

And in your selector (pseudo-code, obviously):

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

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

return NulloDataTemplate;

HTH, Kent

Kent Boogaart
"WPF matches an object with its DataTemplate by exact runtime type" -- Not true. If you add a DataTemplate with DataType=BaseClass, it will match SubClass as well. I've seen it work. Unfortunately, the framework specifically disallows making a DataTemplate for System.Object; you get a runtime error "The type 'DataTemplateKey' failed construction. DataTemplate.DataType cannot be type Object."
Joe White
You're right. I was thinking of Styles, which aren't automatically inherited. Updating my answer. Thanks.
Kent Boogaart
+1  A: 

I'm not sure about replacing the default DataTemplate, but you can use a ValueConverter to pass display ToString in the case of certain types and an empty string otherwise. Here's some code (note that the typeb textblock doesnt have the converter on it to show what it looks like normally):

.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
    }
}
Mark Synowiec