Home > Software engineering >  How to properly bind Dictionary in xaml c#?
How to properly bind Dictionary in xaml c#?

Time:03-29

I have troble binding my Dictionary to show in xaml. When I bind Months into ItemsSource it says No DataContext found for Binding "Months". Do I need DataContext and where do I need to add it?

This is my sample code:

namespace DictionaryTest
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            Dictionary<string, Month> m = new Dictionary<string, Month>();
            m.Add("1", new Month("January", 0));
            m.Add("2", new Month("February", 1));
            m.Add("3", new Month("March", 2));
            m.Add("4", new Month("April", 3));

            Resources["Months"] = m;

            InitializeComponent();
        }

        public class Month
        {
            public Month(string name, int popularity)
            {
                Name = name;
                Popularity = popularity;
            }
            public string Name { get; set; }
            public int Popularity { get; set; }
        }
    }
}

App.xaml.cs:

namespace DictionaryTest
{
    public partial class App : Application
    {

    }
}

and my MainWindow.xaml:

<Window x:Class="DictionaryTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:DictionaryTest"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <ListView 
            ItemsSource="{Binding Path=Months}">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="Key"
                            DisplayMemberBinding="{Binding Key}" />
                    <GridViewColumn Header="Name"
                            DisplayMemberBinding="{Binding Value.Name}" />
                    <GridViewColumn Header="Popularity"
                            DisplayMemberBinding="{Binding Value.Popularity}" />
                </GridView>
            </ListView.View>
        </ListView>
    </Grid>
</Window>

CodePudding user response:

You will need to set the DataContext directly to be the MainWindow (although you may want to look into the MVVM pattern further).

In order to achieve this, you will need to declare your dictionary as a property, and set the DataContext, like:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        Months = new Dictionary<string, Month>();
        Months.Add("1", new("January", 0));
        Months.Add("2", new("February", 1));
        Months.Add("3", new("March", 2));
        Months.Add("4", new("April", 3));

        InitializeComponent();

        // This line tells the Xaml where to find find the data, in this case it's MainWindow
        DataContext = this;
    }

    public Dictionary<string, Month> Months { get; }

    public class Month
    {
        public Month(string name, int popularity)
        {
            Name = name;
            Popularity = popularity;
        }

        public string Name { get; set; }
        public int Popularity { get; set; }
    }
}

No need for the Resources in the constructor.

  • Related