buckley
buckley

Reputation: 14089

Bind the tab header to a property from code

I am binding a collection to a TabControl using its ItemSource property.

I'm programming WPF in code and not in XAML to get a deeper understanding.

The problem I'm faced with is that if I want to bind the header of a TabItem to a property ("EntityID") the binding does not kick in.

The code works if I set a value instead of a binding (code below in comments)

var binding = new Binding();
binding.Path = new PropertyPath("EntityID");

DataTemplate itemTemplate = new DataTemplate();
var label = new FrameworkElementFactory(typeof(Label));

//label.SetValue(Label.ContentProperty,"test");
label.SetBinding(Label.ContentProperty, binding);

itemTemplate.VisualTree = label;

_tabControl.ItemTemplate = itemTemplate;

Furthermore, if set the ContentTemplate instead of the ItemTemplate the binding works as well.

How can I bind the tab header to a property of my ItemsSource from purely code?

Upvotes: 0

Views: 1623

Answers (2)

Vinit Sankhe
Vinit Sankhe

Reputation: 19885

Couple of things...

As a WPF designer and developer, XAML is the best way of GUI and Code Behind segregation. It does not decrease my understanding of WPF in any way. So I recommend XAML.

Believe me being a Winforms / ASP.NET developer myself, I was initially reluctant of using XAML, but the titanic amount of code that I had to write and the relationships between various GUI elements and upon that taming the beasts called Templates \ Styles \ Triggers and ResourceDictionaries just using C# code behind was just a plain torture to me.

Enough of my experience, this is about your issue!!

To answer your question, have you set _tabControl.ItemsSource? And make sure that each item from that ItemsSource has EntityID property in it. Your code should work.

If this still doesnt work then try to see in your Visual Studio's Output window, if there are any binding errors.

Upvotes: 1

Sisyphe
Sisyphe

Reputation: 4684

There are many ways to set bindings from Code Behind. What you should try to bind is the HeaderProperty on the TabItem. Though you must first retrieve it to do that.

Here is a working example that should set you started. It's not the way I would do it, as I would do that in xaml, but as you requested to do that from code behind, here you go :)

On a side note, it's almost always a bad idea to define templates in Code behind, try to avoid it as much as possible.

Windows.xaml

<Window x:Class="StackOverflow.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:sys="clr-namespace:System;assembly=mscorlib"
    xmlns:local="clr-namespace:StackOverflow"
    Title="Super long title of the super window" Width="500" Height="300">

    <Window.Resources>
        <DataTemplate DataType="{x:Type local:Entity}">
            <TextBlock Text="{Binding Id}" FontSize="{Binding Size}" />
        </DataTemplate>
    </Window.Resources>

    <local:MyTabControl x:Name="tabControl" ItemsSource="{Binding Entities}" />

</Window>

Window.xaml.cs

using System.Windows;
using System;
using System.Windows.Data;
using System.Collections.Generic;
using System.Windows.Controls;

namespace StackOverflow
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{

    public MainWindow()
    {
        InitializeComponent();
        DataContext = this;
    }

    public IEnumerable<Entity> Entities
    {
        get
        {
            for (int i = 0; i < 5; i++)
            {
                yield return new Entity() { Id = i };
            }
        }
    }
}

public class MyTabControl : TabControl
{
    protected override DependencyObject GetContainerForItemOverride()
    {
        var tabitem = base.GetContainerForItemOverride() as TabItem;
        if (tabitem != null)
        {
            tabitem.Loaded += OnTabItemLoaded;
        }
        return tabitem;
    }

    void OnTabItemLoaded(object sender, RoutedEventArgs e)
    {
        var tabItem = sender as TabItem;
        if (tabItem == null)
            throw new InvalidOperationException();
        tabItem.SetBinding(TabItem.HeaderProperty, new Binding("DisplayName"));
    }
}

public class Entity : DependencyObject
{
    public int Id { get; set; }
    public string DisplayName { get { return "Entity ID : " + Id; } }
}
}

Upvotes: 1

Related Questions