1

I'm using MahApps for my first Wpf project, and more specifically tabControls. I tested it on a tiny test project. It worked well, until I tried to merge my code in my project.

Here's an example of my code behind :

public class Datas
{
    public ObservableCollection<string> titles { get; set; }

    public Datas()
    {
        init();
    }

    public void init()
    {
        titles = new ObservableCollection<string>()
        {
            "Title 1",
            "Title 2",
            "Title 3",
            "Title 4"
        };
    }
}

public partial class Window1 : MetroWindow
{
    private Datas datas;

    public Window1()
    {
        init();
    }

    private void init()
    {
        datas = new Datas();
        this.DataContext = this;
    }
}

And my Xaml code :

<TabControl DataContext="{Binding Datas}">
    <TabControl.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding titles}"/>
        </DataTemplate>
    </TabControl.ItemTemplate>
    <TabControl.ContentTemplate>
        <DataTemplate>
            <TextBlock Text="Content" />
        </DataTemplate>
    </TabControl.ContentTemplate>
</TabControl>

I've been searching for few days so far. I've found a topic about dataBinding to another class but it doesn't seem to work for me. Not sure if I can use both DataContexts in my Window1 class, even if I tried something like binding multiple controls to different dataContexts.

Do I really need something like that ? It seems to be bigger than what I need but I may be wrong. So, my problem is that I would like to have my tabs whose titles are those in my list, and it doesn't display anything (no error when running though).

Thanks for your help, and please be slow in your answers, I'm still new to Wpf :)

Community
  • 1
  • 1
Adrana
  • 79
  • 11

2 Answers2

1

The Window:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <TabControl ItemsSource="{Binding Titles}">
            <TabControl.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding}"/>
                </DataTemplate>
            </TabControl.ItemTemplate>
            <TabControl.ContentTemplate>
                <DataTemplate>
                    <TextBlock Text="Content" />
                </DataTemplate>
            </TabControl.ContentTemplate>
        </TabControl>
    </Grid>
</Window>

The Window's code behind:

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            this.DataContext = new Datas();
            this.InitializeComponent();
        }
    }

    public class Datas
    {
        private ObservableCollection<String> titles;
        public ObservableCollection<String> Titles
        {
            get
            {
                if (this.titles == null)
                {
                    this.titles = new ObservableCollection<String>()
                    {
                        "Title 1",
                        "Title 2",
                        "Title 3",
                        "Title 4"
                    };
                }
                return this.titles;
            }
        }
    }

Some advices:

  • Binding only works with public properties.

  • Do not expose an ObservableCollection if you are not going to modify it, use IList instead (it is lighter).

  • In WPF, at least for properties, lazy initialization is more natural than constructor initialization (see the Titles property).

  • Take a look at the .NET capitalization conventions, prefer using Pascal Casing for properties.

Raúl Nuño
  • 313
  • 2
  • 12
  • Woohoo ! It works ! Thank you so much http://stackoverflow.com/users/1378699/raul-nuno it's been so painful to find something like that ! Thanks for your link and your advices, I'll read / follow them asap, I didn't think it was so "complicated" to do that. But what if I want to use more than one DataContext ? And is there any reason that you put it above the InitializeComponent() method ? – Adrana May 23 '14 at 10:08
  • You are welcome! There is only one DataContext. Your ViewModel is the Datas class, put there all you want to expose to the View. The reason for putting code above or below the InitializeComponent method is well explained [here](http://stackoverflow.com/a/11965931/1378699). – Raúl Nuño May 23 '14 at 10:28
  • Ok, I got it. I started to do something like that but I'll have to rewrite my code... Well, interesting topic, I always tried to put it at the end haha. I'll try to find something about bindings debug too, I always wondered why it hasn't been implemented yet. – Adrana May 23 '14 at 11:27
0

Set ItemsSource of TabControl and defind public property Datas in your Window's DataContext

 <TabControl ItemsSource="{Binding Datas.titles}">
   <TabControl.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding}"/>
            </DataTemplate>
        </TabControl.ItemTemplate>



 public partial class Window1 : MetroWindow
{


    public Window1()
    {
        init();
    }

    private void init()
    {
        Datas = new Datas();
        this.DataContext = this;
    }

     public Datas Datas{get;set;}
}
Nitin
  • 18,344
  • 2
  • 36
  • 53
  • Thanks for your help nit, but it doesn't work for me, it still displays nothing. If I'm not wrong, the ItemsSource might be the public property, so I did, and then . I don't think I missed something in your code... – Adrana May 23 '14 at 09:10
  • can you check your output window for binding errors? – Nitin May 23 '14 at 09:24
  • As I said, I'm new to WPF. I checked it out quickly on how to do that, and it should returns me warnings if binding failed. It doesn't here – Adrana May 23 '14 at 09:34
  • As nit said, you have to check the Output window (within Visual Studio) for lines containing "System.Windows.Data Error". Binding errors are not shown in your application, they simply don't work. – Raúl Nuño May 23 '14 at 10:04