Specify a default empty DataTemplate instead of the default 'ToString()' DataTemplate

前端 未结 6 1340
囚心锁ツ
囚心锁ツ 2021-02-19 10:11

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

相关标签:
6条回答
  • 2021-02-19 10:50

    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;
    
    0 讨论(0)
  • 2021-02-19 10:55

    I used Nullable, worked for my situation.

    <DataTemplate DataType="{x:Type sys:Nullable}">
    <!-- Content -->
    </DataTemplate>
    
    0 讨论(0)
  • 2021-02-19 11:02

    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
        }
    }
    
    0 讨论(0)
  • 2021-02-19 11:12

    Here a working example about how to do this using a selector (the best way 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
        }
    }
    
    0 讨论(0)
  • 2021-02-19 11:13

    If you are using the MVVM pattern and have an abstract class which all your ViewModel classes derive from, you can use that class instead of System.Object:

    <Grid.Resources>
        <DataTemplate DataType="{x:Type vm:VMBase}">
        </DataTemplate>
    </Grid.Resources>
    
    0 讨论(0)
  • 2021-02-19 11:17

    I discovered something accidentally. I was using a custom dependency property to set the Datacontext on a usercontrol that had a contentcontrol with Datatemplates based on types(entities in my case). Since I had several different kinds of entities my custom dependency property was

    ` typeof(object)
    

    This was the device I used to bind to the datacontext of the ContentControl.

     public object MySelectedItem
        {
            get { return (object)GetValue(Property1Property); }
            set { SetValue(Property1Property, value); }
        }
    
                public static readonly DependencyProperty Property1Property
            = DependencyProperty.Register(
                  "MySelectedItem",
                  typeof(object),
                  typeof(PromotionsMenu),
                  new PropertyMetadata(false)
              );
    

    Used like this:

     MySelectedItem = SomeEntity;
    

    I discovered I could also use it like this:

     MySelectedItem = "some text";
    

    And the contextcontrol would print some text as its context.

    MySelectedItem = "";
    

    works for a totally blank context.

    `

    0 讨论(0)
提交回复
热议问题