Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I solve a toolbar bug with DataTemplates?

(Wpf, .Net4)

Hey, When I use a Data Template with DataType (and no key) it only applies in the constructor. (I must use it that way because I have two different type). The thing is, it works on .net 3.5, and now I need to upgrade to .net 4. (I played with the properties of the project and saw that it's working on 3.5) This is the entire code (except for the default App.xaml):

MainWindow.xaml:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication1" x:Name="me"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="100" />
            <RowDefinition />
        </Grid.RowDefinitions>
        <ToolBar ItemsSource="{Binding ElementName=me, Path=Items}">
            <ToolBar.Resources>
                <DataTemplate  DataType="{x:Type local:Class1}">
                    <TextBlock Text="{Binding Title}" />
                </DataTemplate>
            </ToolBar.Resources>
        </ToolBar>

        <StackPanel Grid.Row="1">
            <Button Content="1"  Click="Button_Click"/>
        </StackPanel>
    </Grid>
</Window>

MainWindow.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Collections.ObjectModel;

namespace WpfApplication1
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            Items = new ObservableCollection<Class1>();
            Items.Add(new Class1() { Title = "1" });

            InitializeComponent();
        }

        public ObservableCollection<Class1> Items { get; set; }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            Items.Add(new Class1() { Title = (Items.Count + 1).ToString() });
        }
    }

    public class Class1
    {
        public string Title { get; set; }
    }
}

The button adds items dynamicly, we can see the first one shows its title, and the dynamicly added items doesn't have a template applied. What can I do? thanks.

like image 443
user2283268 Avatar asked Dec 06 '25 00:12

user2283268


1 Answers

Apparently after rendering Toolbar doesn`t use default Class1 template anymore. There are several solutions that can work here depending on requirements.

1) Define DataTemplate in App.xaml:

<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary>
                <DataTemplate DataType="{x:Type TestWPF:Class1}">
                    <TextBlock Text="{Binding Title}" />
                </DataTemplate>
            </ResourceDictionary>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Application.Resources>

Assuming you have some other resource dictionaries there as well. If not, DataTemplate can be placed right into Application.Resources without all that Dictionary stuff.

2) When an object doesn`t have a default template it just uses its ToString method to represent itself visually. So your Class1 (and others) can override ToString:

public class Class1
{
    public string Title { get; set; }

    public override string ToString()
    {
       return Title;
    }
}

3) Standard WPF approach for ItemControls - have ItemTemplate:

 <ToolBar ItemsSource="{Binding ElementName=me, Path=Items}">
     <ToolBar.ItemTemplate>
         <DataTemplate>
             <TextBlock Text="{Binding Title}" />
         </DataTemplate>
     </ToolBar.ItemTemplate>
 </ToolBar>

But you said that there are several types that should have templates so for this to work you will have to implement ItemTemplateSelector for ToolBar.

like image 119
icebat Avatar answered Dec 08 '25 14:12

icebat